Merge branch 'master' of http://139.196.74.78:10010/r/jagzwxm/ja_web
17 files modified
6 files deleted
290 files added
| | |
| | | @saber:registry=https://center.javablade.com/api/packages/blade/npm/ |
| | | //center.javablade.com/api/packages/blade/npm/:_authToken=66c6549d47896da834ef4a84b5fcbf4763744b28 |
| | | registry="https://registry.npmmirror.com" |
| | | #依赖开启严格模式 |
| | | strict-peer-dependencies=true |
| | | # 自动安装对等依赖,无需手动安装 |
| | | auto-install-peers=true |
| | |
| | | { |
| | | "printWidth": 120, |
| | | "tabWidth": 2, |
| | | "semi": false, |
| | | "singleAttributePerLine": false, |
| | | "bracketSpacing": true, |
| | | "singleQuote": true, |
| | | "quoteProps": "preserve", |
| | | "arrowParens": "avoid", |
| | | "endOfLine": "crlf", |
| | | "htmlWhitespaceSensitivity": "ignore", |
| | | "bracketSameLine": false, |
| | | "proseWrap": "preserve", |
| | | "useTabs": true, |
| | | "trailingComma": "es5", |
| | | "spaceBeforeFunctionParen": true, |
| | | "overrides": [ |
| | | { |
| | | "files": "*.scss", |
| | | "options": { |
| | | "parser": "scss", |
| | | "tabWidth": 4, |
| | | "singleQuote": false |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | "printWidth": 120, |
| | | "tabWidth": 2, |
| | | "semi": false, |
| | | "singleAttributePerLine": false, |
| | | "bracketSpacing": true, |
| | | "singleQuote": true, |
| | | "quoteProps": "preserve", |
| | | "arrowParens": "avoid", |
| | | "endOfLine": "crlf", |
| | | "htmlWhitespaceSensitivity": "ignore", |
| | | "bracketSameLine": false, |
| | | "proseWrap": "preserve", |
| | | "useTabs": true, |
| | | "trailingComma": "es5", |
| | | "spaceBeforeFunctionParen": true, |
| | | "overrides": [ |
| | | { |
| | | "files": "*.scss", |
| | | "options": { |
| | | "parser": "scss", |
| | | "tabWidth": 4, |
| | | "singleQuote": false |
| | | } |
| | | } |
| | | ] |
| | | } |
| | |
| | | "build:test": "vite build --mode test", |
| | | "build:prod": "vite build --mode production", |
| | | "serve": "vite preview --host" |
| | | }, |
| | | "dependencies": { |
| | | "@amap/amap-jsapi-loader": "catalog:", |
| | | "@ztzf/apis": "workspace:*", |
| | | "@ztzf/components": "workspace:*", |
| | | "@ztzf/constants": "workspace:*", |
| | | "@ztzf/hooks": "workspace:*", |
| | | "@ztzf/utils": "workspace:*", |
| | | "@dvgis/dc-sdk": "catalog:", |
| | | "@element-plus/icons-vue": "catalog:", |
| | | "@saber/nf-design-base-elp": "catalog:", |
| | | "@saber/nf-form-design-elp": "catalog:", |
| | | "@saber/nf-form-elp": "catalog:", |
| | | "@smallwei/avue": "catalog:", |
| | | "@turf/turf": "catalog:", |
| | | "animate.css": "catalog:", |
| | | "avue-plugin-ueditor": "catalog:", |
| | | "axios": "catalog:", |
| | | "cesium": "catalog:", |
| | | "codemirror": "catalog:", |
| | | "crypto-js": "catalog:", |
| | | "dayjs": "catalog:", |
| | | "decimal.js": "catalog:", |
| | | "disable-devtool": "catalog:", |
| | | "echarts": "catalog:", |
| | | "element-plus": "catalog:", |
| | | "eventemitter3": "catalog:", |
| | | "highlight.js": "catalog:", |
| | | "html5-qrcode": "catalog:", |
| | | "hull.js": "catalog:", |
| | | "js-audio-recorder": "catalog:", |
| | | "js-base64": "catalog:", |
| | | "js-cookie": "catalog:", |
| | | "js-md5": "catalog:", |
| | | "jszip": "catalog:", |
| | | "leaflet": "catalog:", |
| | | "leaflet-ant-path": "catalog:", |
| | | "lodash": "catalog:", |
| | | "mathjs": "catalog:", |
| | | "mitt": "catalog:", |
| | | "mqtt": "catalog:", |
| | | "nprogress": "catalog:", |
| | | "qrcodejs2-fix": "catalog:", |
| | | "reconnecting-websocket": "catalog:", |
| | | "sm-crypto": "catalog:", |
| | | "trtc-sdk-v5": "catalog:", |
| | | "uuid": "catalog:", |
| | | "vant": "catalog:", |
| | | "video.js": "catalog:", |
| | | "videojs-markers": "catalog:", |
| | | "vue": "catalog:", |
| | | "vue-i18n": "catalog:", |
| | | "vue-router": "catalog:", |
| | | "vue3-clipboard": "catalog:", |
| | | "vuedraggable": "catalog:", |
| | | "vuex": "catalog:", |
| | | "xlsx": "catalog:" |
| | | }, |
| | | "devDependencies": { |
| | | "@dvgis/vite-plugin-dc": "catalog:", |
| | | "@vitejs/plugin-basic-ssl": "catalog:", |
| | | "@vitejs/plugin-vue": "catalog:", |
| | | "@vue/compiler-sfc": "catalog:", |
| | | "postcss-pxtorem": "catalog:", |
| | | "prettier": "catalog:", |
| | | "sass": "catalog:", |
| | | "terser": "catalog:", |
| | | "unplugin-auto-import": "catalog:", |
| | | "vite": "catalog:", |
| | | "vite-plugin-compression": "catalog:", |
| | | "vite-plugin-minipic": "catalog:", |
| | | "vite-plugin-svg-icons": "catalog:", |
| | | "vite-plugin-vue-setup-extend": "catalog:" |
| | | } |
| | | } |
| | |
| | | return Promise.reject(new Error(error)); |
| | | } |
| | | ); |
| | | |
| | | window._request = axios |
| | | export default axios; |
| | |
| | | "build:blackBox": "vite build --mode blackBox", |
| | | "serve": "vite preview --host", |
| | | "format": "prettier --write \"src/**/*.+(js|ts|jsx|tsx)\"" |
| | | }, |
| | | "dependencies": { |
| | | "@amap/amap-jsapi-loader": "catalog:", |
| | | "@ztzf/apis": "workspace:*", |
| | | "@ztzf/components": "workspace:*", |
| | | "@ztzf/constants": "workspace:*", |
| | | "@ztzf/hooks": "workspace:*", |
| | | "@ztzf/utils": "workspace:*", |
| | | "@dvgis/dc-sdk": "catalog:", |
| | | "@element-plus/icons-vue": "catalog:", |
| | | "@saber/nf-design-base-elp": "catalog:", |
| | | "@saber/nf-form-design-elp": "catalog:", |
| | | "@saber/nf-form-elp": "catalog:", |
| | | "@smallwei/avue": "catalog:", |
| | | "@turf/turf": "catalog:", |
| | | "animate.css": "catalog:", |
| | | "avue-plugin-ueditor": "catalog:", |
| | | "axios": "catalog:", |
| | | "cesium": "catalog:", |
| | | "codemirror": "catalog:", |
| | | "crypto-js": "catalog:", |
| | | "dayjs": "catalog:", |
| | | "decimal.js": "catalog:", |
| | | "disable-devtool": "catalog:", |
| | | "echarts": "catalog:", |
| | | "element-plus": "catalog:", |
| | | "eventemitter3": "catalog:", |
| | | "highlight.js": "catalog:", |
| | | "html5-qrcode": "catalog:", |
| | | "hull.js": "catalog:", |
| | | "js-audio-recorder": "catalog:", |
| | | "js-base64": "catalog:", |
| | | "js-cookie": "catalog:", |
| | | "js-md5": "catalog:", |
| | | "jszip": "catalog:", |
| | | "leaflet": "catalog:", |
| | | "leaflet-ant-path": "catalog:", |
| | | "lodash": "catalog:", |
| | | "mathjs": "catalog:", |
| | | "mitt": "catalog:", |
| | | "mqtt": "catalog:", |
| | | "nprogress": "catalog:", |
| | | "qrcodejs2-fix": "catalog:", |
| | | "reconnecting-websocket": "catalog:", |
| | | "sm-crypto": "catalog:", |
| | | "trtc-sdk-v5": "catalog:", |
| | | "uuid": "catalog:", |
| | | "vant": "catalog:", |
| | | "video.js": "catalog:", |
| | | "videojs-markers": "catalog:", |
| | | "vue": "catalog:", |
| | | "vue-i18n": "catalog:", |
| | | "vue-router": "catalog:", |
| | | "vue3-clipboard": "catalog:", |
| | | "vuedraggable": "catalog:", |
| | | "vuex": "catalog:", |
| | | "xlsx": "catalog:" |
| | | }, |
| | | "devDependencies": { |
| | | "@dvgis/vite-plugin-dc": "catalog:", |
| | | "@vitejs/plugin-basic-ssl": "catalog:", |
| | | "@vitejs/plugin-vue": "catalog:", |
| | | "@vue/compiler-sfc": "catalog:", |
| | | "postcss-pxtorem": "catalog:", |
| | | "prettier": "catalog:", |
| | | "sass": "catalog:", |
| | | "terser": "catalog:", |
| | | "unplugin-auto-import": "catalog:", |
| | | "vite": "catalog:", |
| | | "vite-plugin-compression": "catalog:", |
| | | "vite-plugin-minipic": "catalog:", |
| | | "vite-plugin-svg-icons": "catalog:", |
| | | "vite-plugin-vue-setup-extend": "catalog:" |
| | | } |
| | | } |
| | |
| | | isErrorShown = true |
| | | showToast('用户令牌不可用,请重新登录'); |
| | | const transmitData = { data: { type: 'tokenExpired' } } |
| | | |
| | | |
| | | wx.miniProgram.reLaunch({url: 'pages/login/index'}) |
| | | wx.miniProgram.postMessage(transmitData) |
| | | uni.postMessage(transmitData) |
| | | |
| | | |
| | | removeToken() |
| | | removeRefreshToken() |
| | | // 重定向到登录页 |
| | |
| | | // message: message, |
| | | // type: status === -2 ? 'warning' : 'error', |
| | | // }) |
| | | showToast(message); |
| | | showToast(message) |
| | | return Promise.reject(new Error(message)) |
| | | } |
| | | return res |
| | |
| | | return Promise.reject(new Error(error)) |
| | | } |
| | | ) |
| | | |
| | | window._request = axios |
| | | export default axios |
| | |
| | | "build:test": "vite build --mode test", |
| | | "build:prod": "vite build --mode production", |
| | | "serve": "vite preview --host" |
| | | }, |
| | | "dependencies": { |
| | | "@amap/amap-jsapi-loader": "catalog:", |
| | | "@ztzf/apis": "workspace:*", |
| | | "@ztzf/components": "workspace:*", |
| | | "@ztzf/constants": "workspace:*", |
| | | "@ztzf/hooks": "workspace:*", |
| | | "@ztzf/utils": "workspace:*", |
| | | "@dvgis/dc-sdk": "catalog:", |
| | | "@element-plus/icons-vue": "catalog:", |
| | | "@saber/nf-design-base-elp": "catalog:", |
| | | "@saber/nf-form-design-elp": "catalog:", |
| | | "@saber/nf-form-elp": "catalog:", |
| | | "@smallwei/avue": "catalog:", |
| | | "@turf/turf": "catalog:", |
| | | "animate.css": "catalog:", |
| | | "avue-plugin-ueditor": "catalog:", |
| | | "axios": "catalog:", |
| | | "cesium": "catalog:", |
| | | "codemirror": "catalog:", |
| | | "crypto-js": "catalog:", |
| | | "dayjs": "catalog:", |
| | | "decimal.js": "catalog:", |
| | | "disable-devtool": "catalog:", |
| | | "echarts": "catalog:", |
| | | "element-plus": "catalog:", |
| | | "eventemitter3": "catalog:", |
| | | "highlight.js": "catalog:", |
| | | "html5-qrcode": "catalog:", |
| | | "hull.js": "catalog:", |
| | | "js-audio-recorder": "catalog:", |
| | | "js-base64": "catalog:", |
| | | "js-cookie": "catalog:", |
| | | "js-md5": "catalog:", |
| | | "jszip": "catalog:", |
| | | "leaflet": "catalog:", |
| | | "leaflet-ant-path": "catalog:", |
| | | "lodash": "catalog:", |
| | | "mathjs": "catalog:", |
| | | "mitt": "catalog:", |
| | | "mqtt": "catalog:", |
| | | "nprogress": "catalog:", |
| | | "qrcodejs2-fix": "catalog:", |
| | | "reconnecting-websocket": "catalog:", |
| | | "sm-crypto": "catalog:", |
| | | "trtc-sdk-v5": "catalog:", |
| | | "uuid": "catalog:", |
| | | "vant": "catalog:", |
| | | "video.js": "catalog:", |
| | | "videojs-markers": "catalog:", |
| | | "vue": "catalog:", |
| | | "vue-i18n": "catalog:", |
| | | "vue-router": "catalog:", |
| | | "vue3-clipboard": "catalog:", |
| | | "vuedraggable": "catalog:", |
| | | "vuex": "catalog:", |
| | | "xlsx": "catalog:" |
| | | }, |
| | | "devDependencies": { |
| | | "@dvgis/vite-plugin-dc": "catalog:", |
| | | "@vitejs/plugin-basic-ssl": "catalog:", |
| | | "@vitejs/plugin-vue": "catalog:", |
| | | "@vue/compiler-sfc": "catalog:", |
| | | "postcss-pxtorem": "catalog:", |
| | | "prettier": "catalog:", |
| | | "sass": "catalog:", |
| | | "terser": "catalog:", |
| | | "unplugin-auto-import": "catalog:", |
| | | "vite": "catalog:", |
| | | "vite-plugin-compression": "catalog:", |
| | | "vite-plugin-minipic": "catalog:", |
| | | "vite-plugin-svg-icons": "catalog:", |
| | | "vite-plugin-vue-setup-extend": "catalog:" |
| | | } |
| | | } |
| | |
| | | return Promise.reject(new Error(error)); |
| | | } |
| | | ); |
| | | |
| | | window._request = axios |
| | | export default axios; |
| | |
| | | "dev:drone-command": "pnpm -C applications/drone-command dev", |
| | | "dev:mobile-web-view": "pnpm -C applications/mobile-web-view dev", |
| | | "dev:task-work-order": "pnpm -C applications/task-work-order dev", |
| | | "dev:work-app": "pnpm -C uniapps/work-app dev:h5", |
| | | "dev:work-wx": "pnpm -C uniapps/work-wx dev:h5", |
| | | "prod": "pnpm -r prod", |
| | | "prod:drone-command": "pnpm -C applications/drone-command prod", |
| | | "prod:mobile-web-view": "pnpm -C applications/mobile-web-view prod", |
| | |
| | | }, |
| | | "workspaces": [ |
| | | "applications/*", |
| | | "packages/*" |
| | | "packages/*", |
| | | "uniapps/*" |
| | | ], |
| | | "keywords": [], |
| | | "author": "", |
| | |
| | | "@zip.js/zip.js": "2.7.34" |
| | | }, |
| | | "onlyBuiltDependencies": [ |
| | | "sharp" |
| | | "@parcel/watcher", |
| | | "core-js", |
| | | "es5-ext", |
| | | "esbuild", |
| | | "protobufjs", |
| | | "sharp", |
| | | "vue-demi" |
| | | ] |
| | | }, |
| | | "dependencies": { |
| | | "@amap/amap-jsapi-loader": "^1.0.1", |
| | | "@dvgis/dc-sdk": "3.4.0", |
| | | "@dvgis/vite-plugin-dc": "2.2.0", |
| | | "@element-plus/icons-vue": "^2.3.1", |
| | | "@saber/nf-design-base-elp": "^1.3.0", |
| | | "@saber/nf-form-design-elp": "^1.4.1", |
| | | "@saber/nf-form-elp": "^1.4.4", |
| | | "@smallwei/avue": "^3.6.2", |
| | | "@turf/turf": "^6.5.0", |
| | | "@ztzf/apis": "workspace:*", |
| | | "@ztzf/components": "workspace:*", |
| | | "@ztzf/constants": "workspace:*", |
| | | "@ztzf/hooks": "workspace:*", |
| | | "@ztzf/utils": "workspace:*", |
| | | "animate.css": "^4.1.1", |
| | | "avue-plugin-ueditor": "^1.0.4", |
| | | "axios": "^1.8.3", |
| | | "cesium": "1.126.0", |
| | | "codemirror": "^5.65.16", |
| | | "crypto-js": "^4.1.1", |
| | | "dayjs": "^1.10.6", |
| | | "decimal.js": "^10.4.3", |
| | | "disable-devtool": "^0.3.8", |
| | | "echarts": "^5.6.0", |
| | | "element-plus": "2.9.11", |
| | | "eventemitter3": "^5.0.1", |
| | | "highlight.js": "^11.9.0", |
| | | "html5-qrcode": "^2.3.8", |
| | | "hull.js": "^1.0.6", |
| | | "js-audio-recorder": "^1.0.7", |
| | | "js-base64": "^3.7.4", |
| | | "js-cookie": "^3.0.0", |
| | | "js-md5": "^0.7.3", |
| | | "jszip": "^3.10.1", |
| | | "leaflet": "^1.9.4", |
| | | "leaflet-ant-path": "^1.3.0", |
| | | "lodash": "^4.17.21", |
| | | "mathjs": "10.0.0", |
| | | "mitt": "^3.0.1", |
| | | "mqtt": "^5.11.0", |
| | | "nprogress": "^0.2.0", |
| | | "postcss-pxtorem": "^6.1.0", |
| | | "qrcodejs2-fix": "^0.0.1", |
| | | "reconnecting-websocket": "^4.4.0", |
| | | "sm-crypto": "^0.3.13", |
| | | "trtc-sdk-v5": "^5.14.0", |
| | | "uuid": "^11.1.0", |
| | | "vant": "^4.9.21", |
| | | "video.js": "^8.23.4", |
| | | "videojs-markers": "^1.0.1", |
| | | "vue": "^3.5.13", |
| | | "vue-i18n": "^9.1.9", |
| | | "vue-router": "^4.3.2", |
| | | "vue3-clipboard": "^1.0.0", |
| | | "vuedraggable": "^4.1.0", |
| | | "vuex": "^4.1.0", |
| | | "xlsx": "^0.18.5" |
| | | }, |
| | | "devDependencies": { |
| | | "@vitejs/plugin-basic-ssl": "^1.1.0", |
| | | "@vitejs/plugin-vue": "^5.0.4", |
| | | "@vue/compiler-sfc": "^3.4.27", |
| | | "prettier": "^2.8.7", |
| | | "sass": "^1.85.1", |
| | | "terser": "^5.31.1", |
| | | "unplugin-auto-import": "^0.11.2", |
| | | "vite": "5.2.12", |
| | | "vite-plugin-compression": "^0.5.1", |
| | | "vite-plugin-minipic": "^1.3.0", |
| | | "vite-plugin-svg-icons": "^2.0.1", |
| | | "vite-plugin-vue-setup-extend": "^0.4.0" |
| | | "prettier": "catalog:" |
| | | } |
| | | } |
| | |
| | | import request from '@/axios'; |
| | | |
| | |
| | | export * from './common'; |
| | | export * from './deivce'; |
| | | export * from './job'; |
| | | export * from './wayline'; |
| | | export * from './workOrder'; |
| | |
| | | import request from '@/axios'; |
| | | export const getAreaDataByAlgorithmKeysApi = (data) => { |
| | | return request({ |
| | | return window._request({ |
| | | url: `/drone-device-core/layer/api/v1/getAreaDataByAlgorithmKeys`, |
| | | method: 'post', |
| | | data, |
| | |
| | | |
| | | // 获取执行任务航线详情 |
| | | export const getJobWayLineDetails = params => { |
| | | return request({ |
| | | return window._request({ |
| | | url: '/drone-device-core/wayline/waylineJobInfo/jobWaylineDetails', |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | } |
| | |
| | | "private": true, |
| | | "description": "公共api", |
| | | "main": "index.js", |
| | | "license": "ISC" |
| | | "license": "ISC", |
| | | "peerDependencies": { |
| | | "axios": "catalog:" |
| | | }, |
| | | "devDependencies": { |
| | | "axios": "catalog:" |
| | | } |
| | | } |
| | |
| | | "private": true, |
| | | "description": "钩子", |
| | | "main": "index.js", |
| | | "license": "ISC" |
| | | "license": "ISC", |
| | | "peerDependencies": { |
| | | "leaflet": "catalog:", |
| | | "@turf/turf": "catalog:", |
| | | "cesium": "catalog:" |
| | | }, |
| | | "dependencies": { |
| | | "@ztzf/apis": "workspace:*" |
| | | }, |
| | | "devDependencies": { |
| | | "leaflet": "catalog:", |
| | | "@turf/turf": "catalog:", |
| | | "cesium": "catalog:" |
| | | } |
| | | } |
| | |
| | | "private": true, |
| | | "description": "工具类", |
| | | "main": "index.js", |
| | | "license": "ISC" |
| | | "license": "ISC", |
| | | "peerDependencies": { |
| | | "cesium": "catalog:", |
| | | "dayjs": "catalog:", |
| | | "decimal.js": "catalog:" |
| | | }, |
| | | "devDependencies": { |
| | | "cesium": "catalog:", |
| | | "dayjs": "catalog:", |
| | | "decimal.js": "catalog:" |
| | | } |
| | | } |
| | |
| | | packages: |
| | | - 'applications/*' |
| | | - 'packages/*' |
| | | - "applications/*" |
| | | - "packages/*" |
| | | - "uniapps/*" |
| | | |
| | | catalog: |
| | | "@amap/amap-jsapi-loader": "^1.0.1" |
| | | "@dvgis/dc-sdk": "3.4.0" |
| | | "@dvgis/vite-plugin-dc": "2.2.0" |
| | | "@element-plus/icons-vue": "^2.3.1" |
| | | "@saber/nf-design-base-elp": "^1.3.0" |
| | | "@saber/nf-form-design-elp": "^1.4.1" |
| | | "@saber/nf-form-elp": "^1.4.4" |
| | | "@smallwei/avue": "^3.6.2" |
| | | "@turf/turf": "^6.5.0" |
| | | "animate.css": "^4.1.1" |
| | | "avue-plugin-ueditor": "^1.0.4" |
| | | "axios": "^1.8.3" |
| | | "cesium": "1.126.0" |
| | | "codemirror": "^5.65.16" |
| | | "crypto-js": "^4.1.1" |
| | | "dayjs": "^1.10.6" |
| | | "decimal.js": "^10.4.3" |
| | | "disable-devtool": "^0.3.8" |
| | | "echarts": "^5.6.0" |
| | | "element-plus": "2.9.11" |
| | | "eventemitter3": "^5.0.1" |
| | | "highlight.js": "^11.9.0" |
| | | "html5-qrcode": "^2.3.8" |
| | | "hull.js": "^1.0.6" |
| | | "js-audio-recorder": "^1.0.7" |
| | | "js-base64": "^3.7.4" |
| | | "js-cookie": "^3.0.0" |
| | | "js-md5": "^0.7.3" |
| | | "jszip": "^3.10.1" |
| | | "leaflet": "^1.9.4" |
| | | "leaflet-ant-path": "^1.3.0" |
| | | "lodash": "^4.17.21" |
| | | "mathjs": "10.0.0" |
| | | "mitt": "^3.0.1" |
| | | "mqtt": "^5.11.0" |
| | | "nprogress": "^0.2.0" |
| | | "postcss-pxtorem": "^6.1.0" |
| | | "qrcodejs2-fix": "^0.0.1" |
| | | "reconnecting-websocket": "^4.4.0" |
| | | "sm-crypto": "^0.3.13" |
| | | "trtc-sdk-v5": "^5.14.0" |
| | | "uuid": "^11.1.0" |
| | | "vant": "^4.9.21" |
| | | "video.js": "^8.23.4" |
| | | "videojs-markers": "^1.0.1" |
| | | "vue": "^3.5.13" |
| | | "vue-i18n": "^9.1.9" |
| | | "vue-router": "^4.3.2" |
| | | "vue3-clipboard": "^1.0.0" |
| | | "vuedraggable": "^4.1.0" |
| | | "vuex": "^4.1.0" |
| | | "xlsx": "^0.18.5" |
| | | |
| | | # build/dev 工具 |
| | | "@vitejs/plugin-basic-ssl": "^1.1.0" |
| | | "@vitejs/plugin-vue": "^5.0.4" |
| | | "@vue/compiler-sfc": "^3.4.27" |
| | | "prettier": "^2.8.7" |
| | | "sass": "^1.85.1" |
| | | "terser": "^5.31.1" |
| | | "unplugin-auto-import": "^0.11.2" |
| | | "vite": "5.2.12" |
| | | "vite-plugin-compression": "^0.5.1" |
| | | "vite-plugin-minipic": "^1.3.0" |
| | | "vite-plugin-svg-icons": "^2.0.1" |
| | | "vite-plugin-vue-setup-extend": "^0.4.0" |
| New file |
| | |
| | | # 告诉EditorConfig插件,这是根文件,不用继续往上查找 |
| | | root = true |
| | | |
| | | # 匹配全部文件 |
| | | [*] |
| | | # 设置字符集 |
| | | charset = utf-8 |
| | | # 缩进风格,可选space、tab |
| | | indent_style = space |
| | | # 缩进的空格数 |
| | | indent_size = 2 |
| | | # 结尾换行符,可选lf、cr、crlf |
| | | end_of_line = lf |
| | | # 在文件结尾插入新行 |
| | | insert_final_newline = true |
| | | # 删除一行中的前后空格 |
| | | trim_trailing_whitespace = true |
| | | |
| | | # 匹配md结尾的文件 |
| | | [*.md] |
| | | insert_final_newline = false |
| | | trim_trailing_whitespace = false |
| New file |
| | |
| | | # Logs |
| | | logs |
| | | *.log |
| | | npm-debug.log* |
| | | yarn-debug.log* |
| | | yarn-error.log* |
| | | pnpm-debug.log* |
| | | lerna-debug.log* |
| | | |
| | | node_modules |
| | | .DS_Store |
| | | dist |
| | | *.local |
| | | |
| | | # Editor directories and files |
| | | .idea |
| | | *.suo |
| | | *.ntvs* |
| | | *.njsproj |
| | | *.sln |
| | | *.sw? |
| | | |
| | | #user |
| | | .hbuilderx |
| | | unpackage |
| | | /stats.html |
| | | # pnpm-lock.yaml |
| | | yarn.lock |
| | | package-lock.json |
| New file |
| | |
| | | # 掌控智飞 |
| | | |
| | | ``` |
| | | npm install pnpm -g |
| | | pnpm install |
| | | pnpm run dev |
| | | |
| | | node:16.18.0 |
| | | npm:更换为淘宝镜像 |
| | | pnpm:8.6.12 |
| | | ``` |
| | | |
| | | # h5更新步骤 |
| | | |
| | | 打开软件,发行,自定义发行,选择对应的环境 |
| | | |
| | | 然后把代码拷贝到服务器上 |
| | | 测试 |
| | | /software/service/drone/web/work-app |
| | | 正式 |
| | | /app/service/drone/web/work-app |
| | | # app更新步骤 |
| | | |
| | | 修改 /src/config 里面的development的参数,改为对应环境的对应变量 |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | # uniapp 团队协作开发实践模板(Vue3) |
| | | |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | |
| | | |
| | | 使用uniapp+vite+vue3+typescript+uview-plus+unocss 搭建的适合团队协作的快速开发模版 |
| | | |
| | | [uview-plus官方文档](https://uiadmin.net/uview-plus/) |
| | | |
| | | 本项目集众多项目的优点,打造最适合团队协作开发的项目模板。 |
| | | |
| | | 国内仓库地址:[https://gitee.com/ouyang/uniapp-vue3-template](https://gitee.com/ouyang/uniapp-vue3-template) |
| | | |
| | | 在线预览地址:[https://oyjt.github.io/uniapp-vue3-template/](https://oyjt.github.io/uniapp-vue3-template/) |
| | | |
| | | ### 特性 |
| | | |
| | | - [x] 集成`uview-plus3.0 ui`库 |
| | | - [x] 支持多环境打包构建 |
| | | - [x] 使用`pinia`状态管理 |
| | | - [x] 封装网络请求,并支持`Typescript` |
| | | - [x] 支持路径别名 |
| | | - [x] 支持自动加载组件和`API` |
| | | - [x] 自动校验`git`提交代码格式 |
| | | - [x] 集成`ESLint`、`StyleLint`、`EditorConfig`代码格式规范 |
| | | - [x] `Typescript`支持 |
| | | - [x] 集成`UnoCSS` |
| | | - [x] 集成`iconify`图标库 |
| | | - [x] 集成`z-paging`下拉刷新功能 |
| | | - [x] 添加页面跳转拦截,登录权限校验 |
| | | - [x] 支持`token`无感刷新 |
| | | - [x] 项目分包 |
| | | - [x] 集成小程序隐私协议授权组件 |
| | | - [x] 项目构建自动删除本地图片并替换本地图片路径为线上图片 |
| | | - [x] 集成包体积视图分析插件 |
| | | - [x] 支持国际化 |
| | | - [x] 集成`alova`网络请求(具体使用请切换到 [feature/alova](https://github.com/oyjt/uniapp-vue3-template/tree/feature/alova) 分支) |
| | | - [x] 集成`axios`网络请求(具体使用请切换到 [feature/axios](https://github.com/oyjt/uniapp-vue3-template/tree/feature/axios) 分支) |
| | | - [x] 支持新的`wot-design-uni`库(具体使用请切换到[feature/wot-design-uni](https://github.com/oyjt/uniapp-vue3-template/tree/feature/wot-design-uni)分支),[wot-design-uni官方文档](https://wot-design-uni.cn/) |
| | | - [x] 支持新的`shadcn-ui`库(具体使用请切换到[feature/shadcn-ui](https://github.com/oyjt/uniapp-vue3-template/tree/feature/shadcn-ui)分支),[shadcn-ui官方文档](https://ui.shadcn.com/) |
| | | - [x] 更好的 `AI` 支持,适配`cursor`和`trae`规则,集成`MCP`插件 |
| | | |
| | | ### uniapp插件推荐 |
| | | - [uniapp 插件精选(https://github.com/oyjt/awesome-uniapp)](https://github.com/oyjt/awesome-uniapp) |
| | | |
| | | ### 目录结构 |
| | | 项目中采用目前最新的技术方案来实现,目录结构清晰。 |
| | | ``` |
| | | uniapp-vue3-project |
| | | ├ build vite配置统一管理 |
| | | │ ├ config |
| | | │ └ plugins |
| | | ├ env 环境变量 |
| | | ├ scripts 一些脚本 |
| | | │ ├ post-upgrade.js 依赖库清理 |
| | | │ └ verify-commit.js git提交检验 |
| | | ├ src |
| | | │ ├ api 接口管理 |
| | | │ ├ components 公共组件 |
| | | │ ├ hooks 常用hooks封装 |
| | | │ ├ locale 国际化语言管理 |
| | | │ ├ pages 页面管理 |
| | | │ ├ plugins 插件管理 |
| | | │ ├ router 路由管理 |
| | | │ ├ static 静态资源 |
| | | │ ├ store 状态管理 |
| | | │ ├ utils 一些工具 |
| | | │ ├ App.vue |
| | | │ ├ main.ts |
| | | │ ├ manifest.json 项目配置 |
| | | │ ├ pages.json 页面配置 |
| | | │ └ uni.scss 全局scss变量 |
| | | ├ types 全局typescript类型文件 |
| | | │ ├ auto-imports.d.ts |
| | | │ ├ components.d.ts |
| | | │ ├ global.d.ts |
| | | │ └ module.d.ts |
| | | ├ LICENSE |
| | | ├ README.md |
| | | ├ cz.config.js cz-git配置 |
| | | ├ eslint.config.js eslint配置 |
| | | ├ index.html |
| | | ├ package.json |
| | | ├ pnpm-lock.yaml |
| | | ├ stylelint.config.js stylelint配置 |
| | | ├ tsconfig.json |
| | | ├ uno.config.ts unocss配置 |
| | | └ vite.config.ts vite配置 |
| | | ``` |
| | | |
| | | #### vite插件管理 |
| | | ``` |
| | | build |
| | | ├ config vite配置 |
| | | │ ├ index.ts 入口文件 |
| | | │ └ proxy.ts 跨域代理配置 |
| | | └ plugins vite插件 |
| | | ├ autoImport.ts 自动导入api |
| | | ├ cleanImage.ts 自动清理图片文件 |
| | | ├ component.ts 自动导入组件 |
| | | ├ index.ts 入口文件 |
| | | ├ replaceUrl.ts 自动替换图片地址为CDN地址 |
| | | ├ unocss.ts unocss配置 |
| | | └ visualizer.ts 包体积视图分析 |
| | | |
| | | ``` |
| | | |
| | | #### 接口管理 |
| | | ``` |
| | | api |
| | | ├ common 通用api |
| | | │ ├ index.ts |
| | | │ └ types.ts |
| | | ├ user 用户相关api |
| | | │ ├ index.ts |
| | | │ └ types.ts |
| | | └ index.ts 入口文件 |
| | | ``` |
| | | |
| | | #### hooks管理 |
| | | ``` |
| | | hooks |
| | | ├ use-clipboard 剪切板 |
| | | │ └ index.ts |
| | | ├ use-loading loading |
| | | │ └ index.ts |
| | | ├ use-modal 模态框 |
| | | │ └ index.ts |
| | | ├ use-permission 校验权限 |
| | | │ └ index.ts |
| | | ├ use-share 分享 |
| | | │ └ index.ts |
| | | └ index.ts 入口文件 |
| | | ``` |
| | | |
| | | ### 页面管理 |
| | | ``` |
| | | pages |
| | | ├ common 公共页面(分包common) |
| | | │ ├ login |
| | | │ │ └ index.vue |
| | | │ └ webview |
| | | │ └ index.vue |
| | | └ tab 主页面(主包) |
| | | ├ home |
| | | │ └ index.vue |
| | | ├ list |
| | | │ └ index.vue |
| | | └ user |
| | | └ index.vue |
| | | ``` |
| | | |
| | | #### 状态管理 |
| | | ``` |
| | | store |
| | | ├ modules |
| | | │ ├ app app状态 |
| | | │ │ ├ index.ts |
| | | │ │ └ types.ts |
| | | │ └ user 用户状态 |
| | | │ ├ index.ts |
| | | │ └ types.ts |
| | | └ index.ts 入口文件 |
| | | ``` |
| | | |
| | | ### 工具方法 |
| | | ``` |
| | | utils |
| | | ├ auth token相关方法 |
| | | │ └ index.ts |
| | | ├ common 通用方法 |
| | | │ └ index.ts |
| | | ├ modals 弹窗相关方法 |
| | | │ └ index.ts |
| | | ├ request 网络请求相关方法 |
| | | │ ├ index.ts |
| | | │ ├ interceptors.ts |
| | | │ ├ status.ts |
| | | │ └ types.ts |
| | | └ index.ts 入口文件 |
| | | ``` |
| | | |
| | | ### 使用方法 |
| | | |
| | | ```bash |
| | | # 安装依赖 |
| | | pnpm install |
| | | |
| | | # 启动H5 |
| | | pnpm dev:h5 |
| | | |
| | | # 启动微信小程序 |
| | | pnpm dev:mp-weixin |
| | | ``` |
| | | |
| | | ### 发布 |
| | | |
| | | ```bash |
| | | # 构建开发环境 |
| | | pnpm build:h5 |
| | | pnpm build:mp-weixin |
| | | |
| | | # 构建测试环境 |
| | | pnpm build:h5-test |
| | | pnpm build:mp-weixin-test |
| | | |
| | | # 构建生产环境 |
| | | pnpm build:h5-prod |
| | | pnpm build:mp-weixin-prod |
| | | ``` |
| | | |
| | | ### 更新uniapp版本 |
| | | |
| | | 更新uniapp相关依赖到最新正式版 |
| | | ```bash |
| | | pnpx @dcloudio/uvm@latest |
| | | ``` |
| | | 或者执行下面的命令 |
| | | ```bash |
| | | pnpm uvm |
| | | ``` |
| | | |
| | | 在升级完后,会自动添加很多无用依赖,执行下面的代码减小保体积 |
| | | ``` |
| | | pnpm uvm-rm |
| | | ``` |
| | | |
| | | ### `v3` 代码块 |
| | | 在 `vue` 文件中,输入 `v3` 按 `tab` 即可快速生成页面模板,可以大大加快页面生成。 |
| | | > 原理:基于 VSCode 代码块生成。 |
| | | |
| | | ### 登录鉴权 |
| | | 1. 页面如果需要登录才能访问,只需在 `pages.json` 文件中需要鉴权的页面下设置 `needLogin` 属性设置为 `true` 即可,比如 |
| | | ``` |
| | | { |
| | | "pages": [ |
| | | { |
| | | "path": "pages/test/test", |
| | | "needLogin": true, |
| | | "style": { |
| | | "navigationBarTitleText": "", |
| | | }, |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | 2. 如果有`tab`页面需要登录才能访问,上面的设置在小程序中点击`tabbar`时无效,因为在小程序中点击tabbar不会触发`uni.switchTab`方法,下面是官方给出的回复及解决方案。 |
| | | |
| | | > 拦截uni.switchTab本身没有问题。但是在微信小程序端点击tabbar的底层逻辑并不是触发uni.switchTab。所以误认为拦截无效,此类场景的解决方案是在tabbar页面的页面生命周期onShow中处理。 |
| | | |
| | | 可参考`pages/tab/user/index.vue`中的代码,核心代码如下: |
| | | ``` |
| | | <script setup lang="ts"> |
| | | // 引入鉴权hooks |
| | | import { usePermission } from "@/hooks"; |
| | | |
| | | onShow(async () => { |
| | | console.log("tabbar page onShow"); |
| | | const hasPermission = await usePermission(); |
| | | console.log(hasPermission ? "已登录" : "未登录,拦截跳转"); |
| | | }); |
| | | </script> |
| | | ``` |
| | | |
| | | ### 注意事项 |
| | | 1. 微信小程序开发者工具中内置的打包分析不准确,本项目使用了`rollup-plugin-visualizer`来分析小程序包体积,默认不开启,有需要的移除相关注释即可 |
| | | 2. 自动构建处理本地图片资源,使用了`vite-plugin-clean-build`和`vite-plugin-replace-image-url`这两个插件,默认不开启相关功能,如果需要使用再`build/vite/plugins/index.ts`文件中移除相关注释即可 |
| | | 3. 使用`vite-plugin-replace-image-url`插件,想要图片自动替换生效,需要在项目中使用绝对路径引入图片资源,如下示例所示。 |
| | | |
| | | 示例一:style中的图片使用 |
| | | ``` |
| | | <template> |
| | | <view :style="`background-image: url('${bgImg}')`"> |
| | | ... |
| | | </view> |
| | | </template> |
| | | <script setup lang="ts"> |
| | | import bgImg from '@/static/images/bg_img.png'; |
| | | </script> |
| | | ``` |
| | | |
| | | 示例二:js中的图片使用 |
| | | |
| | | ``` |
| | | <script setup lang="ts"> |
| | | import walletIcon from '@/static/images/icon_wallet.png'; |
| | | const menuList = [ |
| | | { |
| | | name: 'wallet', |
| | | title: '钱包', |
| | | icon: walletIcon, |
| | | }, |
| | | ... |
| | | ]; |
| | | </script> |
| | | ``` |
| | | |
| | | 示例二:css中的图片使用 |
| | | ``` |
| | | <style lang="scss"> |
| | | .icon { |
| | | background-image: url('@/static/images/icon.png') |
| | | } |
| | | </style> |
| | | ``` |
| | | |
| | | 4. 部分用户构建微信小程序如下错误,原因是微信开发者工具缺失了对应的依赖。 |
| | | ``` |
| | | This @babel/plugin-proposal-private-property-in-object version is not meant to |
| | | be imported. |
| | | ``` |
| | | 此时升级微信开发者工具,或者安装`@babel/plugin-proposal-private-property-in-object`依赖即可解决问题。 |
| | | |
| | | 5. `shadcn-ui` 分支采用最新的 `tailwindcss v4.1` 版本,因为现阶段的 `unocss` 对于最新版 `tailwindcss` 支持还不够完善。 |
| | | `shadcn-ui`并不太适合移动端使用,如果不喜欢可以移除,只保留纯净的框架。 |
| | | |
| New file |
| | |
| | | export * from './proxy' |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:40:50 |
| | | * @FilePath : \build\config\proxy.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import configEnv from "../../src/config/env.js"; |
| | | |
| | | export const createViteProxy = (env,envName = 'development') => { |
| | | const { VITE_APP_PROXY, VITE_API_PREFIX,VITE_APP_ENV } = env |
| | | // 不使用代理直接返回 |
| | | if (!JSON.parse(VITE_APP_PROXY)) return undefined |
| | | const proxy = { |
| | | [VITE_API_PREFIX]: { |
| | | target: configEnv?.[envName || VITE_APP_ENV]?.VITE_API_BASE_URL, |
| | | changeOrigin: true, |
| | | rewrite: path => path.replace(new RegExp(`^${VITE_API_PREFIX}`), ''), |
| | | }, |
| | | } |
| | | return proxy |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 14:51:32 |
| | | * @FilePath : \build\plugins\autoImport.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | /** |
| | | * @name AutoImportDeps |
| | | * @description 按需加载,自动引入 |
| | | */ |
| | | import AutoImport from 'unplugin-auto-import/vite' |
| | | |
| | | export const AutoImportDeps = () => { |
| | | return AutoImport({ |
| | | imports: ['vue', 'uni-app', 'pinia'], |
| | | // 禁用生成 .d.ts 文件,因为项目已转为 JavaScript |
| | | dts: false, |
| | | vueTemplate: true, |
| | | }) |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name cleanImagePlugin |
| | | * @description 清除构建后的图片资源 |
| | | */ |
| | | import CleanBuild from "vite-plugin-clean-build" |
| | | |
| | | export const CleanImagePlugin = () => { |
| | | return CleanBuild({ |
| | | outputDir: "dist/build/mp-weixin", |
| | | patterns: [ |
| | | "static/images/**", |
| | | "!static/images/logo.png", |
| | | "!static/images/tabbar/**" |
| | | ] |
| | | }) |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name AutoRegistryComponents |
| | | * @description 按需加载,自动引入 |
| | | */ |
| | | import Components from 'unplugin-vue-components/vite' |
| | | |
| | | export const AutoRegistryComponents = () => { |
| | | return Components({ |
| | | // 禁用生成 .d.ts 文件,因为项目已转为 JavaScript |
| | | dts: false, |
| | | }) |
| | | } |
| New file |
| | |
| | | import uniPlugin from '@dcloudio/vite-plugin-uni' |
| | | import ViteRestart from 'vite-plugin-restart' |
| | | import { AutoImportDeps } from './autoImport' |
| | | // import { ConfigImageminPlugin } from './imagemin'; |
| | | // import { ReplaceUrlPlugin } from './replaceUrl'; |
| | | import { AutoRegistryComponents } from './component' |
| | | import { MCPPlugin } from './mcp' |
| | | import { ConfigUnoCSSPlugin } from './unocss' |
| | | export default function createVitePlugins (isBuild) { |
| | | const vitePlugins = [ |
| | | // UnoCSS配置 |
| | | ConfigUnoCSSPlugin(), |
| | | // 自动按需引入依赖 |
| | | AutoImportDeps(), |
| | | // 自动按需引入组件(注意:需注册至 uni 之前,否则不会生效) |
| | | AutoRegistryComponents(), |
| | | // uni支持(兼容性写法,当type为module时,必须要这样写) |
| | | uniPlugin.default(), |
| | | ViteRestart({ |
| | | // 通过这个插件,在修改vite.config.js文件则不需要重新运行也生效配置 |
| | | restart: ['vite.config.js'], |
| | | }), |
| | | // 为项目开启 MCP Server |
| | | MCPPlugin(), |
| | | ] |
| | | |
| | | if (isBuild) { |
| | | const buildPlugins = [ |
| | | // 图片资源自动转换为网络资源 |
| | | // ReplaceUrlPlugin(), |
| | | // 自动清除本地图片 |
| | | // CleanImagePlugin(), |
| | | // 打包视图分析 |
| | | // VisualizerPlugin(), |
| | | ] |
| | | vitePlugins.push(...buildPlugins) |
| | | } |
| | | |
| | | return vitePlugins |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name MCPPlugin |
| | | * @description MCP服务 |
| | | */ |
| | | import { VueMcp } from "vite-plugin-vue-mcp" |
| | | |
| | | export const MCPPlugin = () => { |
| | | return VueMcp() |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name ReplaceImageUrl |
| | | * @description 替换图片地址 |
| | | */ |
| | | import replaceImageUrl from 'vite-plugin-replace-image-url' |
| | | |
| | | export const ReplaceUrlPlugin = () => { |
| | | return replaceImageUrl({ |
| | | publicPath: 'https://photo.example.com/miniprogram', |
| | | sourceDir: 'src/static', |
| | | verbose: true, |
| | | }) |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name ConfigUnoCSSPlugin |
| | | * @description UnoCSS相关配置 |
| | | */ |
| | | import UnoCSS from 'unocss/vite' |
| | | |
| | | export const ConfigUnoCSSPlugin = () => { |
| | | return UnoCSS() |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:42:33 |
| | | * @FilePath : \build\plugins\visualizer.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | /** |
| | | * @name VisualizerPlugin |
| | | * @description 打包视图分析 |
| | | */ |
| | | import { visualizer } from 'rollup-plugin-visualizer' |
| | | |
| | | export const VisualizerPlugin = () => { |
| | | return visualizer({ |
| | | emitFile: false, |
| | | filename: 'stats.html', // 分析图生成的文件名 |
| | | open: true, // 如果存在本地服务端口,将在打包后自动展示 |
| | | }) |
| | | } |
| New file |
| | |
| | | /** @type {import('cz-git').CommitizenGitOptions} */ |
| | | export default { |
| | | alias: { fd: 'docs: fix typos' }, |
| | | messages: { |
| | | type: '选择你要提交的类型 :', |
| | | scope: '选择一个提交范围(可选):', |
| | | customScope: '请输入自定义的提交范围 :', |
| | | subject: '填写简短精炼的变更描述 :\n', |
| | | body: '填写更加详细的变更描述(可选)。使用 \'|\' 换行 :\n', |
| | | breaking: '列举非兼容性重大的变更(可选)。使用 \'|\' 换行 :\n', |
| | | footerPrefixesSelect: '选择关联issue前缀(可选):', |
| | | customFooterPrefix: '输入自定义issue前缀 :', |
| | | footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', |
| | | confirmCommit: '是否提交或修改commit ?', |
| | | }, |
| | | types: [ |
| | | { value: 'feat', name: 'feat: 新增功能 | A new feature', emoji: ':sparkles:' }, |
| | | { value: 'fix', name: 'fix: 修复缺陷 | A bug fix', emoji: ':bug:' }, |
| | | { value: 'docs', name: 'docs: 文档更新 | Documentation only changes', emoji: ':memo:' }, |
| | | { value: 'style', name: 'style: 代码格式 | Changes that do not affect the meaning of the code', emoji: ':lipstick:' }, |
| | | { value: 'refactor', name: 'refactor: 代码重构 | A code change that neither fixes a bug nor adds a feature', emoji: ':recycle:' }, |
| | | { value: 'perf', name: 'perf: 性能提升 | A code change that improves performance', emoji: ':zap:' }, |
| | | { value: 'test', name: 'test: 测试相关 | Adding missing tests or correcting existing tests', emoji: ':white_check_mark:' }, |
| | | { value: 'build', name: 'build: 构建相关 | Changes that affect the build system or external dependencies', emoji: ':package:' }, |
| | | { value: 'ci', name: 'ci: 持续集成 | Changes to our CI configuration files and scripts', emoji: ':ferris_wheel:' }, |
| | | { value: 'chore', name: 'chore: 其他修改 | Other changes that don\'t modify src or test files', emoji: ':hammer:' }, |
| | | { value: 'revert', name: 'revert: 回退代码 | Reverts a previous commit', emoji: ':rewind:' }, |
| | | ], |
| | | useEmoji: false, |
| | | emojiAlign: 'center', |
| | | useAI: false, |
| | | aiNumber: 1, |
| | | themeColorCode: '', |
| | | scopes: [], |
| | | allowCustomScopes: true, |
| | | allowEmptyScopes: true, |
| | | customScopesAlign: 'bottom', |
| | | customScopesAlias: 'custom', |
| | | emptyScopesAlias: 'empty', |
| | | upperCaseSubject: false, |
| | | markBreakingChangeMode: false, |
| | | allowBreakingChanges: ['feat', 'fix'], |
| | | breaklineNumber: 100, |
| | | breaklineChar: '|', |
| | | skipQuestions: [], |
| | | issuePrefixes: [{ value: 'closed', name: 'closed: 标记 ISSUES 已完成' }], |
| | | customIssuePrefixAlign: 'top', |
| | | emptyIssuePrefixAlias: 'skip', |
| | | customIssuePrefixAlias: 'custom', |
| | | allowCustomIssuePrefix: true, |
| | | allowEmptyIssuePrefix: true, |
| | | confirmColorize: true, |
| | | minSubjectLength: 0, |
| | | defaultBody: '', |
| | | defaultIssues: '', |
| | | defaultScope: '', |
| | | defaultSubject: '', |
| | | } |
| New file |
| | |
| | | # 页面标题 |
| | | VITE_APP_TITLE=uniapp-vue3模板项目 |
| | | |
| | | # 开发环境配置 |
| | | VITE_APP_ENV=development |
| | | |
| | | # 端口号 |
| | | VITE_APP_PORT=9527 |
| | | |
| | | # h5是否需要配置代理 |
| | | VITE_APP_PROXY=true |
| | | |
| | | # API代理前缀 |
| | | VITE_API_PREFIX=/api |
| | | |
| | | # 删除console |
| | | VITE_DROP_CONSOLE=false |
| New file |
| | |
| | | # 开发环境配置 |
| | | VITE_APP_ENV=development |
| | | |
| | | # 删除console |
| | | VITE_DROP_CONSOLE=false |
| New file |
| | |
| | | # 生产环境配置 |
| | | VITE_APP_ENV=production |
| | | |
| | | # 删除console |
| | | VITE_DROP_CONSOLE=false |
| New file |
| | |
| | | import antfu from '@antfu/eslint-config' |
| | | |
| | | export default antfu( |
| | | { |
| | | unocss: true, |
| | | node: true, |
| | | ignores: [ |
| | | 'dist/**', |
| | | '.vscode/**', |
| | | '.idea/**', |
| | | 'node_modules/**', |
| | | 'src/uni_modules/**', |
| | | 'src/manifest.json', |
| | | 'src/pages.json', |
| | | 'README.md', |
| | | ], |
| | | }, |
| | | { |
| | | rules: { |
| | | // vue顶级标签的顺序 |
| | | 'vue/block-order': ['error', { |
| | | order: ['template', 'script', 'style'], |
| | | }], |
| | | // 不需要尾随逗号 |
| | | 'comma-dangle': ['error', 'never'], |
| | | // 允许console |
| | | 'no-console': 'off', |
| | | // 不需要分号 |
| | | 'style/semi': ['error', 'never'], |
| | | // 块内的空行 |
| | | 'padded-blocks': ['error', 'never'], |
| | | // 顶级函数应使用 function 关键字声明 |
| | | 'antfu/top-level-function': 'off', |
| | | // 全局的 process 不能用 |
| | | 'node/prefer-global/process': 'off', |
| | | // 禁止未使用的捕获组 |
| | | 'regexp/no-unused-capturing-group': 'off', |
| | | // 允许接口和类型别名中的成员之间不使用分隔符 |
| | | 'style/member-delimiter-style': ['error', { |
| | | multiline: { |
| | | delimiter: 'none', |
| | | requireLast: false, |
| | | }, |
| | | singleline: { |
| | | delimiter: 'none', |
| | | requireLast: false, |
| | | }, |
| | | multilineDetection: 'brackets', |
| | | }], |
| | | // if 语句后需要换行 |
| | | 'antfu/if-newline': 'off', |
| | | }, |
| | | }, |
| | | ) |
| New file |
| | |
| | | <!DOCTYPE html> |
| | | <html lang="zh-CN"> |
| | | <head> |
| | | <meta charset="UTF-8" /> |
| | | <script> |
| | | var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
| | | CSS.supports('top: constant(a)')) |
| | | document.write( |
| | | '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
| | | (coverSupport ? ', viewport-fit=cover' : '') + '" />') |
| | | </script> |
| | | <title></title> |
| | | <!--preload-links--> |
| | | <!--app-context--> |
| | | </head> |
| | | <body> |
| | | <div id="app"><!--app-html--></div> |
| | | <script type="module" src="/src/main.js"></script> |
| | | </body> |
| | | </html> |
| New file |
| | |
| | | { |
| | | "name": "work-app", |
| | | "type": "module", |
| | | "version": "1.5.0", |
| | | "description": "掌控智飞", |
| | | "private": true, |
| | | "author": { |
| | | "name": "ztzf" |
| | | }, |
| | | "license": "MIT", |
| | | "homepage": "https://github.com/oyjt/uniapp-vue3-template", |
| | | "repository": { |
| | | "type": "git", |
| | | "url": "https://github.com/oyjt/uniapp-vue3-template.git" |
| | | }, |
| | | "keywords": [], |
| | | "scripts": { |
| | | "preinstall": "npx only-allow pnpm", |
| | | "uvm": "npx @dcloudio/uvm@latest", |
| | | "uvm-rm": "node ./scripts/post-upgrade.js", |
| | | "dev:h5": "uni", |
| | | "dev:h5:ssr": "uni --ssr", |
| | | "dev:h5-test": "uni --mode test", |
| | | "dev:h5-pro": "uni --mode production", |
| | | "dev:mp-weixin": "uni -p mp-weixin", |
| | | "dev:mp-weixin-test": "uni -p mp-weixin --mode test", |
| | | "dev:mp-weixin-prod": "uni -p mp-weixin --mode production", |
| | | "dev:app": "uni -p app", |
| | | "dev:app-android": "uni -p app-android", |
| | | "dev:app-ios": "uni -p app-ios", |
| | | "build:h5": "uni build", |
| | | "build:h5:ssr": "uni build --ssr", |
| | | "build:h5-test": "uni build --mode test", |
| | | "build:h5-prod": "uni build --mode production", |
| | | "build:mp-weixin": "uni build -p mp-weixin", |
| | | "build:mp-weixin-test": "uni build -p mp-weixin --mode test", |
| | | "build:mp-weixin-prod": "uni build -p mp-weixin --mode production", |
| | | "build:app": "uni build -p app", |
| | | "build:app-android": "uni build -p app-android", |
| | | "build:app-ios": "uni build -p app-ios", |
| | | "eslint": "eslint \"src/**/*.{js,jsx,ts,tsx,vue}\"", |
| | | "eslint:fix": "eslint \"src/**/*.{js,jsx,ts,tsx,vue}\" --fix", |
| | | "stylelint": "stylelint \"src/**/*.{vue,scss,css,sass,less}\"", |
| | | "stylelint:fix": "stylelint \"src/**/*.{vue,scss,css,sass,less}\" --fix", |
| | | "cz": "git add . && npx czg", |
| | | "clean": "npx rimraf node_modules", |
| | | "clean:cache": "npx rimraf node_modules/.cache" |
| | | }, |
| | | "dependencies": { |
| | | "@dcloudio/uni-app": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-app-harmony": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-app-plus": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-components": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-h5": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-alipay": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-baidu": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-harmony": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-jd": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-kuaishou": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-lark": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-qq": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-toutiao": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-weixin": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-xhs": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-quickapp-webview": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-ui": "^1.5.11", |
| | | "dayjs": "^1.11.18", |
| | | "js-audio-recorder": "^1.0.7", |
| | | "js-base64": "^3.7.4", |
| | | "js-md5": "^0.7.3", |
| | | "leaflet": "^1.9.4", |
| | | "deep-pick-omit": "1.2.1", |
| | | "destr": "2.0.5", |
| | | "pinia": "2.2.4", |
| | | "pinia-plugin-persistedstate": "4.1.3", |
| | | "trtc-sdk-v5": "^5.14.1", |
| | | "uview-plus": "^3.5.41", |
| | | "vue": "3.4.21", |
| | | "vue-i18n": "9.1.9", |
| | | "z-paging": "^2.8.8" |
| | | }, |
| | | "devDependencies": { |
| | | "@antfu/eslint-config": "5.0.0", |
| | | "@dcloudio/uni-automator": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-cli-shared": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-stacktracey": "3.0.0-4070520250711001", |
| | | "@dcloudio/vite-plugin-uni": "3.0.0-4070520250711001", |
| | | "@esbuild/darwin-arm64": "0.25.1", |
| | | "@esbuild/darwin-x64": "0.25.1", |
| | | "@iconify-json/mdi": "^1.2.3", |
| | | "@rollup/rollup-darwin-arm64": "4.38.0", |
| | | "@rollup/rollup-darwin-x64": "4.38.0", |
| | | "@unocss/eslint-plugin": "^66.3.3", |
| | | "@unocss/preset-icons": "^66.3.3", |
| | | "@vue/runtime-core": "^3.4.21", |
| | | "czg": "^1.12.0", |
| | | "eslint": "^9.32.0", |
| | | "lint-staged": "^16.1.6", |
| | | "miniprogram-api-typings": "^4.1.0", |
| | | "picocolors": "^1.1.1", |
| | | "rimraf": "^6.0.1", |
| | | "rollup-plugin-visualizer": "^6.0.3", |
| | | "sass": "1.79.6", |
| | | "sass-loader": "^16.0.4", |
| | | "stylelint": "^16.23.0", |
| | | "stylelint-config-recess-order": "^6.1.0", |
| | | "stylelint-config-standard": "^39.0.0", |
| | | "stylelint-config-standard-vue": "^1.0.0", |
| | | "unocss": "65.5.0", |
| | | "unocss-preset-weapp": "^66.0.2", |
| | | "unplugin-auto-import": "19.3.0", |
| | | "unplugin-vue-components": "^28.8.0", |
| | | "vite": "5.2.8", |
| | | "vite-plugin-clean-build": "^1.4.1", |
| | | "vite-plugin-replace-image-url": "^1.4.1", |
| | | "vite-plugin-restart": "^1.0.0", |
| | | "vite-plugin-vue-mcp": "^0.3.2" |
| | | }, |
| | | "lint-staged": { |
| | | "src/**/*.{js,jsx}": "eslint --fix", |
| | | "*.{scss,css,style,html}": "stylelint --fix", |
| | | "*.vue": [ |
| | | "eslint --fix", |
| | | "stylelint --fix" |
| | | ] |
| | | }, |
| | | "uni-app": { |
| | | "scripts": { |
| | | "h5-dev": { |
| | | "title": "H5 开发环境", |
| | | "env": { |
| | | "UNI_PLATFORM": "h5", |
| | | "ENV_NAME": "development" |
| | | } |
| | | }, |
| | | "h5-test": { |
| | | "title": "H5 测试环境", |
| | | "env": { |
| | | "UNI_PLATFORM": "h5", |
| | | "ENV_NAME": "test" |
| | | } |
| | | }, |
| | | "h5-prod": { |
| | | "title": "H5 生产环境", |
| | | "env": { |
| | | "UNI_PLATFORM": "h5", |
| | | "ENV_NAME": "production" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "setting": { |
| | | "es6": true, |
| | | "postcss": true, |
| | | "minified": true, |
| | | "uglifyFileName": false, |
| | | "enhance": true, |
| | | "packNpmRelationList": [], |
| | | "babelSetting": { |
| | | "ignore": [], |
| | | "disablePlugins": [], |
| | | "outputPath": "" |
| | | }, |
| | | "useCompilerPlugins": false, |
| | | "minifyWXML": true |
| | | }, |
| | | "compileType": "miniprogram", |
| | | "simulatorPluginLibVersion": {}, |
| | | "packOptions": { |
| | | "ignore": [], |
| | | "include": [] |
| | | }, |
| | | "appid": "wxf7a7651c306981af", |
| | | "editorSetting": {} |
| | | } |
| New file |
| | |
| | | { |
| | | "libVersion": "3.9.1", |
| | | "projectname": "work-app", |
| | | "setting": { |
| | | "urlCheck": true, |
| | | "coverView": true, |
| | | "lazyloadPlaceholderEnable": false, |
| | | "skylineRenderEnable": false, |
| | | "preloadBackgroundData": false, |
| | | "autoAudits": false, |
| | | "showShadowRootInWxmlPanel": true, |
| | | "compileHotReLoad": true |
| | | } |
| | | } |
| New file |
| | |
| | | // # 执行 `pnpm upgrade` 后会升级 `uniapp` 相关依赖 |
| | | // # 在升级完后,会自动添加很多无用依赖,这需要删除以减小依赖包体积 |
| | | // # 只需要执行下面的命令即可 |
| | | |
| | | import { exec } from 'node:child_process' |
| | | |
| | | // 定义要执行的命令 |
| | | const dependencies = [ |
| | | '@dcloudio/uni-app-harmony', |
| | | // TODO: 如果需要某个平台的小程序,请手动删除或注释掉 |
| | | '@dcloudio/uni-mp-alipay', |
| | | '@dcloudio/uni-mp-baidu', |
| | | '@dcloudio/uni-mp-jd', |
| | | '@dcloudio/uni-mp-kuaishou', |
| | | '@dcloudio/uni-mp-lark', |
| | | '@dcloudio/uni-mp-qq', |
| | | '@dcloudio/uni-mp-toutiao', |
| | | '@dcloudio/uni-mp-xhs', |
| | | '@dcloudio/uni-quickapp-webview', |
| | | '@dcloudio/uni-mp-harmony', |
| | | // vue 已经内置了 @vue/runtime-core,这里移除掉 |
| | | '@vue/runtime-core', |
| | | ] |
| | | |
| | | // 使用exec执行命令 |
| | | exec(`pnpm remove ${dependencies.join(' ')}`, (error, stdout, stderr) => { |
| | | if (error) { |
| | | // 如果有错误,打印错误信息 |
| | | console.error(`执行出错: ${error}`) |
| | | return |
| | | } |
| | | // 打印正常输出 |
| | | console.log(`stdout: ${stdout}`) |
| | | // 如果有错误输出,也打印出来 |
| | | console.error(`stderr: ${stderr}`) |
| | | }) |
| New file |
| | |
| | | <script setup> |
| | | import { onHide, onLaunch, onShow } from "@dcloudio/uni-app"; |
| | | import { useAppStore, useUserStore } from "@/store"; |
| | | import { useGlobalWS } from "@/hooks/useGlobalWS.js"; |
| | | |
| | | const appStore = useAppStore(); |
| | | const userStore = useUserStore(); |
| | | |
| | | useGlobalWS(); |
| | | |
| | | onShow(() => { |
| | | console.log("App Show"); |
| | | }); |
| | | |
| | | onHide(() => { |
| | | console.log("App Hide"); |
| | | }); |
| | | |
| | | onLaunch(() => { |
| | | // 初始化系统信息 |
| | | appStore.initSystemInfo(); |
| | | if (!userStore.userInfo) { |
| | | //不存在则跳转至登录页 |
| | | uni.reLaunch({ |
| | | url: "/pages/login/index", |
| | | }); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | /* 每个页面公共css */ |
| | | @import "uview-plus/index.scss"; |
| | | @import "@/static/styles/common.scss"; |
| | | |
| | | .TUICallKit-mobile { |
| | | position: fixed; |
| | | left: 0; |
| | | top: 0; |
| | | z-index: 9999; |
| | | } |
| | | |
| | | page { |
| | | background-image: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/bg.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | background-attachment: fixed; |
| | | // min-height: 10vh; |
| | | } |
| | | |
| | | .uni-tabbar-border { |
| | | background-color: #f6f6f6 !important; |
| | | } |
| | | |
| | | .uni-page-head__title { |
| | | font-family: Source Han Sans CN, Source Han Sans CN !important; |
| | | font-weight: 400 !important; |
| | | font-size: 17px !important; |
| | | color: #222324 !important; |
| | | } |
| | | |
| | | .uni-page-head { |
| | | background: transparent !important; |
| | | } |
| | | </style> |
| New file |
| | |
| | | import { post, upload } from '@/utils/request' |
| | | |
| | | // 文件上传 |
| | | export const uploadFile = filePath => |
| | | upload('/common/upload', { filePath, name: 'file' }) |
| | | |
| | | // 发送验证码 |
| | | export const sendCode = data => post('/sendCode', { data }) |
| New file |
| | |
| | | import {request} from "@/utils/request" |
| | | |
| | | export const startVoice = data => { |
| | | return request({ |
| | | url: `/drone-device-core/speak/api/v1/startVoice`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | // 上传音频文件 |
| | | export const uploadSpeak = data => { |
| | | return request({ |
| | | url:'/drone-device-core/speak/api/v1/uploadSpeak', |
| | | method: 'post', |
| | | headers: { |
| | | 'Content-Type': 'multipart/form-data', |
| | | }, |
| | | data, |
| | | }) |
| | | } |
| New file |
| | |
| | | import {request} from "@/utils/index.js"; |
| | | |
| | | export const getJobListApi = (data, params) => { |
| | | return request({ |
| | | url: `/drone-device-core/wayline/waylineJobInfo/jobList`, |
| | | method: 'post', |
| | | data, |
| | | params, |
| | | }) |
| | | } |
| New file |
| | |
| | | import {request} from "@/utils/request" |
| | | |
| | | export const getDeviceRegionApi = data => { |
| | | return request({ |
| | | url: '/drone-device-core/manage/api/v1/devices/getDeviceRegion', |
| | | method: 'post', |
| | | data: { hidden_flag: 0, ...data }, |
| | | }) |
| | | } |
| New file |
| | |
| | | import { |
| | | get, |
| | | post, |
| | | request |
| | | } from "@/utils/request" |
| | | |
| | | import website from '@/config/website' |
| | | |
| | | /** 登录 */ |
| | | export const login = data => |
| | | post("/user/login", { |
| | | data, |
| | | custom: { |
| | | auth: false |
| | | } |
| | | }) |
| | | |
| | | /** 验证码登录 */ |
| | | export const loginByCode = data => post("/user/loginByCode", { |
| | | data |
| | | }) |
| | | |
| | | /** 退出登录 */ |
| | | export const logout = () => post("/user/logout") |
| | | |
| | | // 用户登录接口 |
| | | export const loginByUsername = (tenantId, deptId, roleId, username, password, type, key, code) => { |
| | | return request({ |
| | | url: '/blade-auth/oauth/token', |
| | | method: 'post', |
| | | header: { |
| | | 'Tenant-Id': tenantId, |
| | | 'Dept-Id': website.switchMode ? deptId : '', |
| | | 'Role-Id': website.switchMode ? roleId : '', |
| | | 'Captcha-Key': key, |
| | | 'Captcha-Code': code, |
| | | }, |
| | | params: { |
| | | tenantId, |
| | | username, |
| | | password, |
| | | grant_type: 'password', |
| | | scope: 'all', |
| | | type, |
| | | }, |
| | | }) |
| | | } |
| | | export const getUserInfo = () => { |
| | | return request({ |
| | | url: '/blade-system/user/info', |
| | | method: 'get', |
| | | }); |
| | | }; |
| | | export const updateInfo = row => { |
| | | return request({ |
| | | url: '/blade-system/user/update-info', |
| | | method: 'post', |
| | | data: row, |
| | | }); |
| | | }; |
| | | export const updatePassword = (oldPassword, newPassword, newPassword1) => { |
| | | return request({ |
| | | url: '/blade-system/user/update-password', |
| | | method: 'post', |
| | | params: { |
| | | oldPassword, |
| | | newPassword, |
| | | newPassword1, |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 发送通话信息 |
| | | export const sendVoiceCallApi = (data) => { |
| | | return request({ |
| | | url: `/drone-device-core/dp/call/sendVoiceCall`, |
| | | method: 'post', |
| | | data |
| | | }) |
| | | } |
| New file |
| | |
| | | import {request} from "@/utils/index.js"; |
| | | export const getList = (data) => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/eventPage', |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | // 获取状态统计数据 |
| | | export const getstatusCount = (params) => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/getstatusCount', |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | export const getStepInfo = (eventNum) => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/getStepInfo', |
| | | method: 'get', |
| | | params: { eventNum } |
| | | }) |
| | | } |
| | | |
| | | // 修改接口:处理待审核状态,动态构建 FormData 提交 |
| | | export const flowEvent = (data, file) => { |
| | | const formData = new FormData() |
| | | |
| | | // 动态添加非空字段到 FormData |
| | | Object.entries(data).forEach(([key, value]) => { |
| | | if (value !== undefined && value !== null) { |
| | | formData.append(key, value) |
| | | } |
| | | }) |
| | | |
| | | // 如果 file 存在,则添加到 FormData |
| | | if (file) { |
| | | formData.append('file', file) |
| | | } |
| | | for (let [key, value] of formData.entries()) { |
| | | console.log(key, value) |
| | | } |
| | | console.log('formData',formData) |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/flowEvent', |
| | | method: 'post', |
| | | data: formData, |
| | | headers: { |
| | | 'Content-Type': 'multipart/form-data', // 设置为表单数据格式 |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | // 新增接口:获取工单详细信息 |
| | | export const getTicketInfo = (id) => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/getTicketInfo', |
| | | method: 'get', |
| | | params: { id }, // 使用工单 ID 查询 |
| | | }) |
| | | } |
| New file |
| | |
| | | <template> |
| | | <web-view :src="src" @message="viewMessage" :allow="allow"/> |
| | | </template> |
| | | |
| | | |
| | | <script setup> |
| | | |
| | | |
| | | const allow = "accelerometer;ambient-light-sensor;autoplay;battery;camera;clipboard-read;clipboard-write;cross-origin-isolated;display-capture;document-domain;encrypted-media;execution-while-not-rendered;execution-while-out-of-viewport;fullscreen;gamepad;geolocation;gyroscope;hid;idle-detection;local-fonts;magnetometer;microphone;midi;payment;picture-in-picture;publickey-credentials-get;screen-wake-lock;serial;speaker-selection;storage-access;sync-xhr;usb;web-share;xr-spatial-tracking" |
| | | const src = defineModel("src"); |
| | | const emit = defineEmits(["webMessage"]); |
| | | |
| | | function viewMessage(event) { |
| | | messageFun({ |
| | | data: { |
| | | data: { |
| | | arg: event.detail.data[0], |
| | | }, |
| | | type: "WEB_INVOKE_APPSERVICE", |
| | | }, |
| | | }); |
| | | } |
| | | |
| | | // WEB_INVOKE_APPSERVICE |
| | | function messageFun(e) { |
| | | if (e.data.type === "WEB_INVOKE_APPSERVICE") { |
| | | if (e.data.data.arg.type === "tokenExpired") { |
| | | return uni.reLaunch({ |
| | | url: "/pages/login/index", |
| | | }); |
| | | } |
| | | emit("webMessage", e.data.data.arg); |
| | | } |
| | | } |
| | | |
| | | |
| | | onLoad((obj) => { |
| | | // const h5Params = obj?.cs && JSON.parse(obj?.cs) |
| | | // console.log('h5Params', h5Params) |
| | | // h5Params && viewMessage({detail: {data: [h5Params.data]}}) |
| | | }) |
| | | |
| | | onShow(() => { |
| | | if (window && window.addEventListener) |
| | | window.addEventListener("message", messageFun); |
| | | }); |
| | | onHide(() => { |
| | | if (window && window.removeEventListener) |
| | | window.removeEventListener("message", messageFun); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | <template> |
| | | <u-popup :show="modelValue" round="20" @close="closeAgreePrivacy"> |
| | | <view class="p-30rpx"> |
| | | <view class="text-lg text-black font-bold"> |
| | | <span>{{ initTitle }}</span> |
| | | </view> |
| | | |
| | | <view class="flex flex-col"> |
| | | <span class="pt-30rpx text-black font-bold">{{ initSubTitle }}</span> |
| | | <span class="pt-30rpx text-sm text-black" |
| | | >1.为向您提供基本的服务,我们会遵循正当、合法、必要的原则收集和使用必要的信息。</span |
| | | > |
| | | <span class="pt-30rpx text-sm text-black" |
| | | >2.基于您的授权我们可能会收集和使用您的相关信息,您有权拒绝或取消授权。</span |
| | | > |
| | | <span class="pt-30rpx text-sm text-black" |
| | | >3.未经您的授权同意,我们不会将您的信息共享给第三方或用于您未授权的其他用途。</span |
| | | > |
| | | <span class="pt-30rpx text-sm text-black" |
| | | >4.详细信息请您完整阅读<text |
| | | class="text-decoration" |
| | | @click="openPrivacyContract" |
| | | >{{ initPrivacyContractName }}</text |
| | | ></span |
| | | > |
| | | </view> |
| | | |
| | | <view class="mt-30rpx flex items-center justify-around pt-10rpx"> |
| | | <view class="min-w-100px"> |
| | | <button class="button button-default" @click="disagree">拒绝</button> |
| | | </view> |
| | | <view class="min-w-100px"> |
| | | <button |
| | | :id="agreePrivacyId" |
| | | class="button button-primary" |
| | | open-type="agreePrivacyAuthorization" |
| | | @agreeprivacyauthorization="agree" |
| | | > |
| | | 同意 |
| | | </button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </u-popup> |
| | | </template> |
| | | |
| | | <script setup> |
| | | const props = withDefaults(defineProps(), { |
| | | modelValue: false, |
| | | title: "", |
| | | subTitle: "", |
| | | disableCheckPrivacy: true, |
| | | agreePrivacyId: "agree-btn", |
| | | }); |
| | | |
| | | const emit = defineEmits([ |
| | | "update:modelValue", |
| | | "needPrivacyAuthorization", |
| | | "agree", |
| | | "disagree", |
| | | ]); |
| | | // 初始化的标题 |
| | | const initTitle = ref("隐私政策概要"); |
| | | // 初始化的副标题 |
| | | const initSubTitle = ref(""); |
| | | // 隐私政策 |
| | | const initPrivacyContractName = ref("隐私政策"); |
| | | |
| | | // 打开隐私 |
| | | function openAgreePrivacy() { |
| | | emit("update:modelValue", true); |
| | | } |
| | | |
| | | // 关闭隐私 |
| | | function closeAgreePrivacy() { |
| | | emit("update:modelValue", false); |
| | | } |
| | | |
| | | // 需要初始化的数据 |
| | | function initData() { |
| | | initTitle.value = props.title || initTitle.value; |
| | | initSubTitle.value = |
| | | props.subTitle || |
| | | `亲爱的用户,感谢您一直以来的支持!为了更好地保护您的权益,同时遵守相关监管要求,请认真阅读${initPrivacyContractName.value},特向您说明如下:`; |
| | | } |
| | | |
| | | // 检测是否授权 |
| | | function checkPrivacySetting() { |
| | | wx.getPrivacySetting({ |
| | | success: (res) => { |
| | | // 未授权弹框 |
| | | if (res.needAuthorization) { |
| | | initPrivacyContractName.value = res.privacyContractName; |
| | | initData(); |
| | | // 是否禁用 自动检测隐私并弹框 |
| | | if (!props.disableCheckPrivacy) { |
| | | // 需要弹出隐私协议 |
| | | openAgreePrivacy(); |
| | | } |
| | | } else { |
| | | // 用户已经同意过隐私协议,所以不需要再弹出隐私协议,也能调用已声明过的隐私接口 |
| | | // wx.getUserProfile() |
| | | } |
| | | }, |
| | | fail: (e) => { |
| | | console.log(e); |
| | | }, |
| | | }); |
| | | } |
| | | // 打开隐私政策 |
| | | function openPrivacyContract() { |
| | | wx.openPrivacyContract({ |
| | | success: () => {}, // 打开成功 |
| | | fail: (e) => { |
| | | uni.$u.toast(`打开失败:${e}`); |
| | | }, // 打开失败 |
| | | }); |
| | | } |
| | | |
| | | // 同意 |
| | | function agree(e) { |
| | | const buttonId = e.target.id || "agree-btn"; |
| | | emit("agree", buttonId); |
| | | emit("update:modelValue", false); |
| | | } |
| | | |
| | | // 拒绝 |
| | | function disagree() { |
| | | emit("disagree"); |
| | | closeAgreePrivacy(); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // 检测是否授权 |
| | | checkPrivacySetting(); |
| | | |
| | | // // 监听授权 |
| | | // wx.onNeedPrivacyAuthorization((resolve, eventInfo) => { |
| | | // emit('update:modelValue', true); |
| | | // // 回调 |
| | | // emit('needPrivacyAuthorization', resolve, eventInfo); |
| | | // }); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .button { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | //height: 80rpx; |
| | | padding: 10px 20px; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | line-height: 1.5; |
| | | color: #fff; |
| | | text-align: center; |
| | | text-decoration: none; |
| | | border-radius: 18rpx; |
| | | //border-width: 1px; |
| | | //border-style: solid; |
| | | } |
| | | |
| | | .button-lg { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | //height: 80rpx; |
| | | padding: 12px 22px; |
| | | font-size: 14px; |
| | | font-weight: 700; |
| | | line-height: 1.5; |
| | | color: #fff; |
| | | text-align: center; |
| | | text-decoration: none; |
| | | border-radius: 20rpx; |
| | | //border-width: 1px; |
| | | //border-style: solid; |
| | | } |
| | | |
| | | .button-default { |
| | | color: #07c160; |
| | | background-color: rgb(0 0 0 / 5%); |
| | | } |
| | | |
| | | .button-primary { |
| | | color: #fff; |
| | | background-color: #07c160; |
| | | } |
| | | |
| | | button { |
| | | padding: 0; |
| | | margin: 0; |
| | | line-height: inherit; |
| | | background-color: transparent; |
| | | border-radius: 0; |
| | | outline: none; |
| | | } |
| | | |
| | | button::after { |
| | | border: none; |
| | | } |
| | | |
| | | .text-decoration { |
| | | color: #07c160; |
| | | text-decoration: underline; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view> |
| | | <picker |
| | | range-key="label" |
| | | :range="langOptions" |
| | | :value="langIndex" |
| | | @change="handleLangChange" |
| | | > |
| | | <slot> |
| | | <view class="i-mdi-language" :style="langStyle" /> |
| | | </slot> |
| | | </picker> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useI18n } from "vue-i18n"; |
| | | |
| | | const props = defineProps({ |
| | | size: { |
| | | type: Number, |
| | | default: 40, |
| | | required: false, |
| | | }, |
| | | }); |
| | | const emit = defineEmits(["change"]); |
| | | const { locale, t } = useI18n(); |
| | | const langStyle = { |
| | | fontSize: `${props.size}rpx`, |
| | | }; |
| | | const langOptions = computed(() => { |
| | | return [ |
| | | { label: t("locale.en"), value: "en" }, |
| | | { label: t("locale.zh-hans"), value: "zh-Hans" }, |
| | | ]; |
| | | }); |
| | | const langIndex = computed(() => { |
| | | return langOptions.value.findIndex((item) => { |
| | | return item.value === locale.value; |
| | | }); |
| | | }); |
| | | |
| | | function handleLangChange(event) { |
| | | const lang = langOptions.value[event.detail.value].value; |
| | | locale.value = lang; |
| | | uni.setLocale(lang); |
| | | emit("change", lang); |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| New file |
| | |
| | | <template> |
| | | <view class="flex flex-wrap gap-3"> |
| | | <view |
| | | v-for="(item, index) in colors" |
| | | :key="index" |
| | | class="mb-10rpx h-40rpx w-40rpx center cursor-pointer border-4rpx border-gray-300 rounded-4rpx border-solid" |
| | | :class="{ 'border-white': theme === item.name }" |
| | | :style="{ backgroundColor: item.color }" |
| | | @click="changeTheme(item.name)" |
| | | > |
| | | <view v-if="theme === item.name" class="i-mdi-check text-32rpx c-#fff" /> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useAppStore } from "@/store"; |
| | | |
| | | const appStore = useAppStore(); |
| | | |
| | | const colors = [ |
| | | { |
| | | name: "", |
| | | color: "#21d59d", |
| | | }, |
| | | { |
| | | name: "blue", |
| | | color: "#3c9cff", |
| | | }, |
| | | ]; |
| | | |
| | | const theme = computed(() => appStore.getTheme); |
| | | |
| | | function changeTheme(theme) { |
| | | appStore.setTheme(theme); |
| | | } |
| | | </script> |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-12-15 17:51:08 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-16 15:01:04 |
| | | * @FilePath : \src\config\env.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-12-15 17:51:08 |
| | | */ |
| | | // 如果是打包app,需要改这里,h5不需要改这里 |
| | | const development = { |
| | | VITE_APP_ENV:'development', |
| | | // 开发环境这里改为自己的 |
| | | VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper', |
| | | // VITE_APP_WEBVIEW_URL: 'http://localhost:5173/drone-app-web-view/#/webViewWrapper', |
| | | VITE_API_BASE_URL: 'https://wrj.shuixiongit.com/api', |
| | | // VITE_API_BASE_URL: 'https://aisky.org.cn/api', |
| | | VITE_APP_WS_API_URL:'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws', |
| | | |
| | | // 静态资源存放地址' |
| | | VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets' |
| | | } |
| | | |
| | | const test = { |
| | | VITE_APP_ENV: 'test', |
| | | VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper', |
| | | VITE_API_BASE_URL: 'https://wrj.shuixiongit.com/api', |
| | | VITE_APP_WS_API_URL: 'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws', |
| | | // 静态资源存放地址' |
| | | VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets' |
| | | } |
| | | |
| | | const production = { |
| | | VITE_APP_ENV: 'production', |
| | | VITE_APP_WEBVIEW_URL: 'https://aisky.org.cn/drone-app-web-view/#/webViewWrapper', |
| | | VITE_API_BASE_URL: 'https://aisky.org.cn/api', |
| | | VITE_APP_WS_API_URL: 'wss://aisky.org.cn/drone-wss/api/v1/ws', |
| | | // 静态资源存放地址' |
| | | VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets' |
| | | } |
| | | |
| | | export default { |
| | | development, |
| | | test, |
| | | production |
| | | } |
| New file |
| | |
| | | /** |
| | | * 全局配置文件 |
| | | */ |
| | | export default { |
| | | title: '', |
| | | logo: 'S', |
| | | key: 'saber', //配置主键,目前用于存储 |
| | | indexTitle: 'BladeX 微服务平台', |
| | | clientId: 'drone', // 客户端id |
| | | clientSecret: 'drone_secret', // 客户端密钥 |
| | | tenantMode: false, // 是否开启租户模式 |
| | | tenantId: '000000', // 管理组租户编号 |
| | | captchaMode: false, // 是否开启验证码模式 |
| | | switchMode: false, // 是否开启登录切换角色部门 |
| | | lockPage: '/lock', |
| | | tokenTime: 3000, |
| | | tokenHeader: 'Blade-Auth', |
| | | //HTTP状态码白名单 |
| | | statusWhiteList: [], |
| | | //配置首页不可关闭 |
| | | setting: { |
| | | sidebar: 'vertical', |
| | | tag: true, |
| | | debug: true, |
| | | collapse: true, |
| | | search: true, |
| | | color: true, |
| | | lock: true, |
| | | screenshot: true, |
| | | fullscreen: true, |
| | | theme: true, |
| | | menu: true, |
| | | }, |
| | | //首页配置 |
| | | fistPage: { |
| | | // name: '首页', |
| | | // path: '/wel/index', |
| | | name: '门户页', |
| | | path: '/wel/gatewayPage', |
| | | }, |
| | | //配置菜单的属性 |
| | | menu: { |
| | | iconDefault: 'icon-caidan', |
| | | label: 'name', |
| | | path: 'path', |
| | | icon: 'source', |
| | | children: 'children', |
| | | query: 'query', |
| | | href: 'path', |
| | | meta: 'meta', |
| | | }, |
| | | //水印配置 |
| | | watermark: { |
| | | mode: false, |
| | | text: 'BladeX', |
| | | }, |
| | | //oauth2配置 |
| | | oauth2: { |
| | | // 是否开启注册功能 |
| | | registerMode: true, |
| | | // 使用后端工程 @org.springblade.test.Sm2KeyGenerator 获取 |
| | | publicKey: '请配置国密sm2公钥', |
| | | // 第三方系统授权地址 |
| | | authUrl: 'http://localhost/blade-auth/oauth/render', |
| | | // 单点登录系统认证 |
| | | ssoMode: false, // 是否开启单点登录功能 |
| | | ssoBaseUrl: 'http://localhost:8100', // 单点登录系统地址(cloud端口为8100,boot端口为80) |
| | | ssoAuthUrl: '/oauth/authorize?client_id=saber3&response_type=code&redirect_uri=', // 单点登录授权地址 |
| | | ssoLogoutUrl: '/oauth/authorize/logout?redirect_uri=', // 单点登录退出地址 |
| | | redirectUri: 'http://localhost:2888/login', // 单点登录回调地址(Saber服务的登录界面地址) |
| | | }, |
| | | //设计器配置 |
| | | design: { |
| | | // 流程设计器类型(true->nutflow,false->flowable) |
| | | designMode: true, |
| | | // 流程设计器地址(flowable模式) |
| | | designUrl: 'http://localhost:9999', |
| | | // 报表设计器地址(cloud端口为8108,boot端口为80) |
| | | reportUrl: 'http://localhost:8108/ureport', |
| | | // 规则设计引擎地址 |
| | | edgeUrl: 'http://localhost:1880', |
| | | }, |
| | | } |
| New file |
| | |
| | | import useClipboard from "./use-clipboard" |
| | | import useLoading from "./use-loading" |
| | | import useLocation from "./use-location" |
| | | import useModal from "./use-modal" |
| | | import usePermission from "./use-permission" |
| | | import useShare from "./use-share" |
| | | import useTheme from "./use-theme" |
| | | import useTabAddButton from "./useTabAddButton" |
| | | |
| | | export { |
| | | useClipboard, |
| | | useLoading, |
| | | useLocation, |
| | | useModal, |
| | | usePermission, |
| | | useShare, |
| | | useTheme, |
| | | useTabAddButton |
| | | } |
| New file |
| | |
| | | /** |
| | | * 剪切板 |
| | | * @example |
| | | * const {setClipboardData, getClipboardData} = useClipboard() |
| | | * // 设置剪切板 |
| | | * setClipboardData({data: '1234567890'}) |
| | | * // 获取剪切板 |
| | | * const data = await getClipboardData() |
| | | */ |
| | | export default function useClipboard () { |
| | | const setClipboardData = ({ data, showToast = true }) => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.setClipboardData({ |
| | | data, |
| | | showToast, |
| | | success: ({ data }) => resolve(data), |
| | | fail: error => reject(error) |
| | | }) |
| | | }) |
| | | } |
| | | const getClipboardData = () => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.getClipboardData({ |
| | | success: ({ data }) => resolve(data), |
| | | fail: error => reject(error) |
| | | }) |
| | | }) |
| | | } |
| | | return { |
| | | setClipboardData, |
| | | getClipboardData |
| | | } |
| | | } |
| New file |
| | |
| | | /** |
| | | * loading 提示框 |
| | | * @example |
| | | * const {showLoading, hideLoading} = useLoading() |
| | | * // 显示loading |
| | | * showLoading() |
| | | * // 隐藏loading |
| | | * hideLoading() |
| | | */ |
| | | export default function useLoading () { |
| | | const showLoading = (content = "加载中") => { |
| | | uni.showLoading({ |
| | | title: content, |
| | | mask: true |
| | | }) |
| | | } |
| | | const hideLoading = () => { |
| | | uni.hideLoading() |
| | | } |
| | | return { |
| | | showLoading, |
| | | hideLoading |
| | | } |
| | | } |
| New file |
| | |
| | | /** |
| | | * 定位hooks,提供定位相关功能 |
| | | * - 获取位置 |
| | | * - 位置监听 |
| | | * - 地址解析 |
| | | * - 距离计算 |
| | | */ |
| | | export default function useLocation () { |
| | | // 当前位置信息 |
| | | const location = ref(null) |
| | | |
| | | // 定位状态 |
| | | const isLocating = ref(false) |
| | | |
| | | // 是否正在监听位置 |
| | | const isWatching = ref(false) |
| | | |
| | | // 定位错误信息 |
| | | const error = ref(null) |
| | | |
| | | // 历史位置 |
| | | const historyLocations = ref([]) |
| | | |
| | | // 监听位置的定时器ID |
| | | let watchId = null |
| | | |
| | | /** |
| | | * 获取当前位置 |
| | | * @param options 定位选项 |
| | | */ |
| | | const getLocation = (options = {}) => { |
| | | isLocating.value = true |
| | | error.value = null |
| | | |
| | | const defaultOptions = { |
| | | type: "gcj02", |
| | | altitude: false, |
| | | isHighAccuracy: false |
| | | } |
| | | |
| | | const finalOptions = { ...defaultOptions, ...options } |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | uni.getLocation({ |
| | | type: finalOptions.type, |
| | | altitude: finalOptions.altitude, |
| | | isHighAccuracy: finalOptions.isHighAccuracy, |
| | | highAccuracyExpireTime: finalOptions.highAccuracyExpireTime, |
| | | success: res => { |
| | | // 更新当前位置 |
| | | const locationData = { |
| | | ...res, |
| | | timestamp: Date.now() |
| | | } |
| | | |
| | | location.value = locationData |
| | | |
| | | // 添加到历史记录 |
| | | historyLocations.value.push(locationData) |
| | | |
| | | // 只保留最近的20条记录 |
| | | if (historyLocations.value.length > 20) { |
| | | historyLocations.value.shift() |
| | | } |
| | | |
| | | finalOptions.success && finalOptions.success(res) |
| | | resolve(locationData) |
| | | }, |
| | | fail: err => { |
| | | error.value = err |
| | | finalOptions.fail && finalOptions.fail(err) |
| | | reject(err) |
| | | }, |
| | | complete: () => { |
| | | isLocating.value = false |
| | | finalOptions.complete && finalOptions.complete() |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 使用地理编码获取地址信息 |
| | | * @param latitude 纬度 |
| | | * @param longitude 经度 |
| | | */ |
| | | const getAddress = (latitude, longitude) => { |
| | | return new Promise((resolve, reject) => { |
| | | // #ifdef APP-PLUS |
| | | uni.request({ |
| | | url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=YOUR_KEY`, |
| | | success: res => { |
| | | if (res.data && res.data.status === 0) { |
| | | const addressComponent = res.data.result.address_component |
| | | const formattedAddress = |
| | | res.data.result.formatted_addresses.recommend |
| | | |
| | | const addressInfo = { |
| | | nation: addressComponent.nation, |
| | | province: addressComponent.province, |
| | | city: addressComponent.city, |
| | | district: addressComponent.district, |
| | | street: addressComponent.street, |
| | | streetNum: addressComponent.street_number, |
| | | poiName: |
| | | res.data.result.poi_count > 0 |
| | | ? res.data.result.pois[0].title |
| | | : "", |
| | | cityCode: res.data.result.ad_info.city_code |
| | | } |
| | | |
| | | if (location.value) { |
| | | location.value.address = addressInfo |
| | | location.value.formatted = formattedAddress |
| | | } |
| | | |
| | | resolve(addressInfo) |
| | | } else { |
| | | reject(new Error("获取地址信息失败")) |
| | | } |
| | | }, |
| | | fail: err => { |
| | | reject(err) |
| | | } |
| | | }) |
| | | // #endif |
| | | |
| | | // #ifndef APP-PLUS |
| | | // 其他平台可以使用uni.getLocation的geocode参数获取(仅App和微信小程序支持) |
| | | // 或者使用其他地图服务的API |
| | | reject(new Error("当前平台不支持地址解析")) |
| | | // #endif |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 停止监听位置 |
| | | */ |
| | | const stopWatchLocation = () => { |
| | | if (watchId !== null) { |
| | | clearInterval(watchId) |
| | | watchId = null |
| | | } |
| | | |
| | | isWatching.value = false |
| | | } |
| | | |
| | | /** |
| | | * 开始监听位置变化 |
| | | * @param options 定位选项 |
| | | * @param interval 监听间隔,单位毫秒 |
| | | */ |
| | | const watchLocation = (options = {}, interval = 5000) => { |
| | | // 已经在监听,先停止 |
| | | if (isWatching.value) { |
| | | stopWatchLocation() |
| | | } |
| | | |
| | | isWatching.value = true |
| | | |
| | | // 首次定位 |
| | | getLocation(options).catch(err => { |
| | | console.error("监听位置首次定位失败", err) |
| | | }) |
| | | |
| | | // 定时获取位置 |
| | | watchId = window.setInterval(() => { |
| | | if (isWatching.value) { |
| | | getLocation(options).catch(err => { |
| | | console.error("监听位置更新失败", err) |
| | | }) |
| | | } |
| | | }, interval) |
| | | |
| | | return watchId |
| | | } |
| | | |
| | | /** |
| | | * 计算两点间距离(米) |
| | | * @param lat1 第一个点的纬度 |
| | | * @param lon1 第一个点的经度 |
| | | * @param lat2 第二个点的纬度 |
| | | * @param lon2 第二个点的经度 |
| | | * @returns 距离,单位:米 |
| | | */ |
| | | const calculateDistance = (lat1, lon1, lat2, lon2) => { |
| | | const R = 6371000 // 地球半径,单位米 |
| | | const dLat = ((lat2 - lat1) * Math.PI) / 180 |
| | | const dLon = ((lon2 - lon1) * Math.PI) / 180 |
| | | |
| | | const a = |
| | | Math.sin(dLat / 2) * Math.sin(dLat / 2) + |
| | | Math.cos((lat1 * Math.PI) / 180) * |
| | | Math.cos((lat2 * Math.PI) / 180) * |
| | | Math.sin(dLon / 2) * |
| | | Math.sin(dLon / 2) |
| | | |
| | | const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)) |
| | | const distance = R * c |
| | | |
| | | return distance |
| | | } |
| | | |
| | | /** |
| | | * 获取当前位置到目标位置的距离 |
| | | * @param targetLat 目标位置纬度 |
| | | * @param targetLon 目标位置经度 |
| | | * @returns 距离,单位:米,如果当前没有位置信息则返回-1 |
| | | */ |
| | | const getDistanceFromCurrent = (targetLat, targetLon) => { |
| | | if (!location.value) { |
| | | return -1 |
| | | } |
| | | |
| | | return calculateDistance( |
| | | location.value.latitude, |
| | | location.value.longitude, |
| | | targetLat, |
| | | targetLon |
| | | ) |
| | | } |
| | | |
| | | /** |
| | | * 格式化距离显示 |
| | | * @param distance 距离,单位:米 |
| | | * @returns 格式化后的距离字符串 |
| | | */ |
| | | const formatDistance = distance => { |
| | | if (distance < 0) { |
| | | return "未知距离" |
| | | } else if (distance < 1000) { |
| | | return `${Math.round(distance)}米` |
| | | } else { |
| | | return `${(distance / 1000).toFixed(1)}公里` |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 打开导航 |
| | | * @param latitude 目标纬度 |
| | | * @param longitude 目标经度 |
| | | * @param name 目标名称 |
| | | * @param address 目标地址 |
| | | */ |
| | | const openLocation = (latitude, longitude, name = "", address = "") => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.openLocation({ |
| | | latitude, |
| | | longitude, |
| | | name, |
| | | address, |
| | | success: () => resolve(), |
| | | fail: err => reject(err) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 选择位置 |
| | | */ |
| | | const chooseLocation = () => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.chooseLocation({ |
| | | success: res => { |
| | | // 更新当前位置 |
| | | if (res.latitude && res.longitude) { |
| | | const locationData = { |
| | | latitude: res.latitude, |
| | | longitude: res.longitude, |
| | | accuracy: 0, |
| | | verticalAccuracy: 0, |
| | | horizontalAccuracy: 0, |
| | | altitude: 0, |
| | | speed: 0, |
| | | timestamp: Date.now(), |
| | | address: { |
| | | province: "", |
| | | city: "", |
| | | district: "", |
| | | street: "", |
| | | poiName: res.name |
| | | }, |
| | | formatted: res.address |
| | | } |
| | | |
| | | location.value = locationData |
| | | } |
| | | |
| | | resolve(res) |
| | | }, |
| | | fail: err => reject(err) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 自动清理 |
| | | onUnmounted(() => { |
| | | stopWatchLocation() |
| | | }) |
| | | |
| | | return { |
| | | // 状态 |
| | | location, |
| | | isLocating, |
| | | isWatching, |
| | | error, |
| | | historyLocations, |
| | | |
| | | // 方法 |
| | | getLocation, |
| | | getAddress, |
| | | watchLocation, |
| | | stopWatchLocation, |
| | | calculateDistance, |
| | | getDistanceFromCurrent, |
| | | formatDistance, |
| | | openLocation, |
| | | chooseLocation |
| | | } |
| | | } |
| New file |
| | |
| | | /** |
| | | * Dialog 提示框 |
| | | * @example |
| | | * const {showModal} = useModal() |
| | | * showModal('提示内容') |
| | | */ |
| | | export default function useModal () { |
| | | const showModal = (content, options) => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.showModal({ |
| | | title: "温馨提示", |
| | | content, |
| | | showCancel: false, |
| | | confirmColor: "#1677FF", |
| | | success: res => resolve(res), |
| | | fail: () => reject(new Error("Alert 调用失败 !")), |
| | | ...options |
| | | }) |
| | | }) |
| | | } |
| | | return { |
| | | showModal |
| | | } |
| | | } |
| New file |
| | |
| | | import { hasPerm } from "@/plugins/permission" |
| | | import { currentRoute } from "@/router" |
| | | |
| | | // 对某些特殊场景需要在页面onShow生命周期中校验权限: |
| | | // 1.微信小程序端点击tabbar的底层逻辑不触发uni.switchTab |
| | | // 2.h5在浏览器地址栏输入url后跳转不触发uni的路由api |
| | | // 3.首次启动加载的页面不触发uni的路由api |
| | | export default async function usePermission () { |
| | | return hasPerm(currentRoute()) |
| | | } |
| New file |
| | |
| | | /** |
| | | * 小程序分享 |
| | | * @param {object} options |
| | | * @example |
| | | * // 必须要调用onShareAppMessage,onShareTimeline才能正常分享 |
| | | * // 因为小程序平台,必须在注册页面时,主动配置onShareAppMessage, onShareTimeline才可以 |
| | | * // 组合式API是运行时才能注册,框架不可能默认给每个页面都开启这两个分享,所以必须在页面代码里包含这两个API的字符串,才会主动去注册。 |
| | | * // 相关说明链接:https://ask.dcloud.net.cn/question/150353 |
| | | * const {onShareAppMessage, onShareTimeline} = useShare({title: '分享标题', path: 'pages/index/index', query: 'id=1', imageUrl: 'https://xxx.png'}) |
| | | * onShareAppMessage() |
| | | * onShareTimeline() |
| | | */ |
| | | export default function useShare (options) { |
| | | // #ifdef MP-WEIXIN |
| | | const title = options?.title ?? "" |
| | | const path = options?.path ?? "" |
| | | const query = options?.query ?? "" |
| | | const imageUrl = options?.imageUrl ?? "" |
| | | |
| | | const shareApp = (params = {}) => { |
| | | onShareAppMessage(() => { |
| | | return { |
| | | title, |
| | | path: path ? `${path}${query ? `?${query}` : ""}` : "", |
| | | imageUrl, |
| | | ...params |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const shareTime = (params = {}) => { |
| | | onShareTimeline(() => { |
| | | return { |
| | | title, |
| | | query: options?.query ?? "", |
| | | imageUrl, |
| | | ...params |
| | | } |
| | | }) |
| | | } |
| | | return { |
| | | onShareAppMessage: shareApp, |
| | | onShareTimeline: shareTime |
| | | } |
| | | // #endif |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:48:36 |
| | | * @FilePath : \src\hooks\use-theme\index.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import { computed } from "vue" |
| | | import { useAppStore } from "@/store" |
| | | |
| | | /** |
| | | * 主题Hook |
| | | */ |
| | | export default function useTheme () { |
| | | const appStore = useAppStore() |
| | | |
| | | // 当前主题模式 |
| | | const theme = computed(() => appStore.getTheme) |
| | | |
| | | // 是否为深色主题 |
| | | const isDark = computed(() => appStore.getTheme === "dark") |
| | | |
| | | /** |
| | | * 设置主题 |
| | | */ |
| | | const setTheme = mode => { |
| | | appStore.setTheme(mode) |
| | | } |
| | | |
| | | /** |
| | | * 切换主题 |
| | | */ |
| | | const toggleTheme = () => { |
| | | const newTheme = theme.value === "light" ? "dark" : "light" |
| | | appStore.setTheme(newTheme) |
| | | } |
| | | |
| | | return { |
| | | theme, |
| | | isDark, |
| | | setTheme, |
| | | toggleTheme |
| | | } |
| | | } |
| New file |
| | |
| | | import {useUserStore} from "@/store/index.js"; |
| | | import {getEnvObj} from "@/utils/index.js"; |
| | | import {enterRoom} from "@/utils/voiceCallByTX/index.js"; |
| | | import useAppStore from "../store/modules/app/index.js"; |
| | | |
| | | let socketTask = null |
| | | |
| | | export function useGlobalWS() { |
| | | const userStore = useUserStore(); |
| | | const appStore = useAppStore(); |
| | | |
| | | const userId = computed(() => userStore?.userInfo?.user_id) |
| | | const access_token = computed(() => userStore?.userInfo?.access_token) |
| | | const {VITE_APP_WS_API_URL} = getEnvObj() |
| | | |
| | | // 消息处理 |
| | | function messageHandler(payload) { |
| | | switch (payload.biz_code) { |
| | | case 'JOB_ISREFRESH': |
| | | appStore.setJobUpdateKeyAdd() |
| | | break |
| | | case 'DEVICE_ISREFRESH': |
| | | appStore.setDeviceUpdateKeyAdd() |
| | | break |
| | | case 'DOWNLOAD_PROGRESS': |
| | | break |
| | | case 'LOGOUT_USER': |
| | | userStore.setUserInfo(null) |
| | | uni.reLaunch({ |
| | | url: '/pages/login/index' |
| | | }) |
| | | break |
| | | case 'VoiceCall': |
| | | enterRoom(payload, userId.value) |
| | | break |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // 关闭ws |
| | | function closeWS() { |
| | | socketTask?.close({ |
| | | success: () => { |
| | | console.log('ws关闭连接'); |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | // 初始化ws |
| | | function initWS() { |
| | | // 关闭,再连接ws |
| | | closeWS() |
| | | if (!access_token.value) return |
| | | const url = VITE_APP_WS_API_URL |
| | | + `?x-auth-token=${encodeURI(access_token?.value)}` |
| | | + `&model_type=3&workspace-id=${userId.value}` |
| | | // 创建连接 |
| | | socketTask = uni.connectSocket({ |
| | | url: url, |
| | | success: () => { |
| | | console.log('ws连接成功'); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('ws连接失败:', err); |
| | | } |
| | | }); |
| | | // 消息监听 |
| | | socketTask.onMessage((result) => { |
| | | messageHandler(JSON.parse(result.data)) |
| | | }) |
| | | //================================== |
| | | // 监听连接打开 |
| | | socketTask.onOpen((res) => { |
| | | console.log('✅ WebSocket连接已建立') |
| | | // reconnectAttempts = 0 // 连接成功后重置重连次数 |
| | | // 可以在这里发送心跳或订阅消息 |
| | | // startHeartbeat() |
| | | }) |
| | | // 监听连接关闭 |
| | | socketTask.onClose((res) => { |
| | | console.log(`WebSocket连接关闭,代码: ${res.code}, 原因: ${res.reason}`) |
| | | |
| | | // 根据不同的关闭代码处理 |
| | | if (res.code === 1000) { // 正常关闭 |
| | | console.log('连接正常关闭') |
| | | } else if (res.code === 1006) { // 异常关闭 |
| | | console.log('连接异常关闭,尝试重连...') |
| | | } else if (res.code === 1011) { // 服务器内部错误 |
| | | console.log('服务器内部错误(1011),延迟重连...') |
| | | } else { |
| | | console.log('其他原因关闭,尝试重连...') |
| | | } |
| | | }) |
| | | |
| | | // 监听错误 |
| | | socketTask.onError((err) => { |
| | | console.error('WebSocket发生错误:', err) |
| | | }) |
| | | } |
| | | |
| | | |
| | | watch(access_token, initWS, {immediate: true}) |
| | | } |
| New file |
| | |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | |
| | | export default function useTabAddButton (visible) { |
| | | onShow(()=>{ |
| | | // const tabList = uni.getTabBar().list; |
| | | // uni.setTabBarItem({ |
| | | // index: 2, // Tab 的索引(从0开始) |
| | | // visible, |
| | | // }); |
| | | }) |
| | | } |
| New file |
| | |
| | | import { createI18n } from "vue-i18n" |
| | | import en from "./langs/en" |
| | | import zhHans from "./langs/zh-Hans" |
| | | |
| | | const i18n = createI18n({ |
| | | legacy: false, // 必须设置false才能使用Composition API |
| | | globalInjection: true, // 为每个组件注入$为前缀的全局属性和函数 |
| | | locale: uni.getLocale(), |
| | | messages: { |
| | | en, |
| | | "zh-Hans": zhHans |
| | | } |
| | | }) |
| | | |
| | | function setupI18n (app) { |
| | | app.use(i18n) |
| | | } |
| | | |
| | | export { i18n } |
| | | export default setupI18n |
| New file |
| | |
| | | export default { |
| | | locale: { |
| | | auto: "System", |
| | | en: "English", |
| | | "zh-hans": "Chinese" |
| | | }, |
| | | home: { |
| | | intro: "Welcome to uni-app demo", |
| | | "toggle-langs": "Change languages" |
| | | } |
| | | } |
| New file |
| | |
| | | export default { |
| | | locale: { |
| | | auto: "系统", |
| | | en: "英语", |
| | | "zh-hans": "中文" |
| | | }, |
| | | home: { |
| | | intro: "欢迎来到uni-app演示", |
| | | "toggle-langs": "切换语言" |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:39:15 |
| | | * @FilePath : \src\main.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import { createSSRApp } from "vue" |
| | | import App from "@/App.vue" |
| | | import setupPlugins from "@/plugins" |
| | | // 引入UnoCSS |
| | | import "virtual:uno.css" |
| | | import 'leaflet/dist/leaflet.css' |
| | | import './static/fonts/font.css' |
| | | import {getEnvObj} from "@/utils/index.js"; |
| | | console.log('当前环境变量',getEnvObj()) |
| | | export function createApp () { |
| | | const app = createSSRApp(App) |
| | | app.use(setupPlugins) |
| | | |
| | | return { |
| | | app |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "name" : "掌控智飞", |
| | | "appid" : "__UNI__0981D7F", |
| | | "description" : "", |
| | | "versionName" : "1.0.0", |
| | | "versionCode" : "100", |
| | | "transformPx" : false, |
| | | /* 5+App特有相关 */ |
| | | "app-plus" : { |
| | | "orientation" : [ |
| | | //竖屏正方向 |
| | | "portrait-primary", |
| | | //竖屏反方向 |
| | | "portrait-secondary", |
| | | //横屏正方向 |
| | | "landscape-primary", |
| | | //横屏反方向 |
| | | "landscape-secondary", |
| | | //自然方向 |
| | | "default" |
| | | ], |
| | | "usingComponents" : true, |
| | | "nvueStyleCompiler" : "uni-app", |
| | | "compilerVersion" : 3, |
| | | "splashscreen" : { |
| | | "alwaysShowBeforeRender" : true, |
| | | "waiting" : true, |
| | | "autoclose" : true, |
| | | "delay" : 0 |
| | | }, |
| | | /* 模块配置 */ |
| | | "modules" : {}, |
| | | /* 应用发布信息 */ |
| | | "distribute" : { |
| | | /* android打包配置 */ |
| | | "android" : { |
| | | "permissions" : [ |
| | | "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", |
| | | "<uses-permission android:name=\"android.permission.VIBRATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.READ_LOGS\"/>", |
| | | "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", |
| | | "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", |
| | | "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.CAMERA\"/>", |
| | | "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", |
| | | "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", |
| | | "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", |
| | | "<uses-feature android:name=\"android.hardware.camera\"/>", |
| | | "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>", |
| | | "<uses-permission android:name=\"android.permission.RECORD_AUDIO\" />" |
| | | ] |
| | | }, |
| | | /* ios打包配置 */ |
| | | "ios" : { |
| | | "dSYMs" : false |
| | | }, |
| | | /* SDK配置 */ |
| | | "sdkConfigs" : {}, |
| | | "icons" : { |
| | | "android" : { |
| | | "hdpi" : "src/static/images/app-logo.png", |
| | | "xhdpi" : "src/static/images/app-logo.png", |
| | | "xxhdpi" : "src/static/images/app-logo.png", |
| | | "xxxhdpi" : "src/static/images/app-logo.png" |
| | | } |
| | | } |
| | | }, |
| | | "nativePlugins" : { |
| | | "TRTCCloudUniPlugin-TRTCCloudImpl" : { |
| | | "__plugin_info__" : { |
| | | "name" : "【官方】腾讯云实时音视频SDK", |
| | | "description" : "uni-app TRTC SDK 是腾讯云实时音视频通讯解决方案在 uni-app 上的 SDK,提供实时音视频服务", |
| | | "platforms" : "Android,iOS", |
| | | "url" : "https://ext.dcloud.net.cn/plugin?id=7774", |
| | | "android_package_name" : "uni.app.UNI0981D7F", |
| | | "ios_bundle_id" : "", |
| | | "isCloud" : true, |
| | | "bought" : 1, |
| | | "pid" : "7774", |
| | | "parameters" : {} |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | /* 快应用特有相关 */ |
| | | "quickapp" : {}, |
| | | /* 小程序特有相关 */ |
| | | "mp-weixin" : { |
| | | "appid" : "wx05742eafb412a57a", |
| | | "setting" : { |
| | | "urlCheck" : false |
| | | }, |
| | | "usingComponents" : true |
| | | }, |
| | | "mp-alipay" : { |
| | | "usingComponents" : true |
| | | }, |
| | | "mp-baidu" : { |
| | | "usingComponents" : true |
| | | }, |
| | | "mp-toutiao" : { |
| | | "usingComponents" : true |
| | | }, |
| | | "uniStatistics" : { |
| | | "enable" : false |
| | | }, |
| | | "vueVersion" : "3", |
| | | "h5" : { |
| | | "router" : { |
| | | "mode" : "hash", |
| | | "base" : "/work-app/" |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "easycom": { |
| | | "custom": { |
| | | "^u--(.*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^up-(.*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)": "z-paging/components/z-paging$1/z-paging$1.vue" |
| | | } |
| | | }, |
| | | "pages": [ |
| | | { |
| | | "path": "pages/work/index", |
| | | "style": { |
| | | "navigationBarTitleText": "事件工单", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/voiceCall/index", |
| | | "style": { |
| | | "navigationBarTitleText": "通话", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/map/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | |
| | | { |
| | | "path": "pages/user/index", |
| | | "style": { |
| | | "navigationBarTitleText": "我的", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/login/index", |
| | | "style": { |
| | | "navigationBarTitleText": "登录页", |
| | | "navigationStyle": "custom" |
| | | } |
| | | } |
| | | ], |
| | | "subPackages": [ |
| | | { |
| | | "root": "subPackages", |
| | | "pages": [ |
| | | { |
| | | "path": "404/index", |
| | | "style": { |
| | | "navigationBarTitleText": "404", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/index", |
| | | "style": { |
| | | "navigationBarTitleText": "工单详情" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/addWork/index", |
| | | "style": { |
| | | "navigationBarTitleText": "新建工单" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/mapWork/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图展示", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "userDetail/infos/index", |
| | | "style": { |
| | | "navigationBarTitleText": "个人资料" |
| | | } |
| | | }, |
| | | { |
| | | "path": "userDetail/password/index", |
| | | "style": { |
| | | "navigationBarTitleText": "修改密码" |
| | | } |
| | | }, |
| | | { |
| | | "path": "browser/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图" |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | "tabBar": { |
| | | "color": "#8c8c8c", |
| | | "selectedColor": "#1D6FE9", |
| | | "borderStyle": "black", |
| | | "backgroundColor": "#ffffff", |
| | | "list": [ |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_order.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.png", |
| | | "pagePath": "pages/work/index", |
| | | "text": "工单" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_order.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.png", |
| | | "pagePath": "pages/voiceCall/index", |
| | | "text": "通话" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_home1.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_home_selected.png", |
| | | "pagePath": "pages/map/index", |
| | | "text": "地图" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_me.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_me_selected.png", |
| | | "pagePath": "pages/user/index", |
| | | "text": "我的" |
| | | } |
| | | ] |
| | | }, |
| | | "globalStyle": { |
| | | "navigationBarTextStyle": "black", |
| | | "navigationBarTitleText": "uni-app", |
| | | "navigationBarBackgroundColor": "#F8F8F8", |
| | | "backgroundColor": "#F8F8F8" |
| | | } |
| | | } |
| New file |
| | |
| | | <!-- 登录页 --> |
| | | <template> |
| | | <view class="login-form-wrap"> |
| | | <image class="logo" :src="logoSvg" /> |
| | | <div class="title">掌控智飞</div> |
| | | <div class="user-name"> |
| | | <image :src="usernameSvg" /> |
| | | <input v-model="loginForm.username" placeholder="请输入用户名" /> |
| | | </div> |
| | | <div class="pass-word"> |
| | | <image :src="passwordSvg" /> |
| | | <input |
| | | v-model="loginForm.password" |
| | | type="password" |
| | | placeholder="请输入密码" |
| | | /> |
| | | </div> |
| | | <div class="remember-password"> |
| | | <label> |
| | | <checkbox-group @change="toggleRemember"> |
| | | <checkbox |
| | | :checked="rememberPassword" |
| | | color="#1D6FE9" |
| | | style="transform: scale(0.7)" |
| | | /> |
| | | </checkbox-group> |
| | | 记住密码 |
| | | </label> |
| | | </div> |
| | | |
| | | <button class="login-btn" :style="[inputStyle]" @tap="submit">登录</button> |
| | | <image class="lowerRightCorner" :src="droneSvg" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getAssetsImage } from "@/utils/index.js"; |
| | | import md5 from "js-md5"; |
| | | import { loginByUsername } from "@/api/user/index.js"; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | |
| | | import { HOME_PATH, LOGIN_PATH, removeQueryString } from "@/router"; |
| | | import { onMounted } from "vue"; |
| | | |
| | | const droneSvg = getAssetsImage("/images/login/droneSvg.svg"); |
| | | const usernameSvg = getAssetsImage("/images/login/username.svg"); |
| | | const passwordSvg = getAssetsImage("/images/login/password.svg"); |
| | | const logoSvg = getAssetsImage("/images/login/logo.svg"); |
| | | |
| | | const userStore = useUserStore(); |
| | | const loginForm = ref({ |
| | | username: "", |
| | | password: "", |
| | | }); |
| | | const rememberPassword = ref(false); |
| | | const inputStyle = computed(() => { |
| | | const style = {}; |
| | | if (loginForm.value.username && loginForm.value.password) { |
| | | style.color = "#fff"; |
| | | style.backgroundColor = "#1D6FE9"; |
| | | } |
| | | return style; |
| | | }); |
| | | let redirect = HOME_PATH; |
| | | function toggleRemember(e) { |
| | | rememberPassword.value = e.detail.value.length > 0; |
| | | } |
| | | |
| | | async function submit() { |
| | | if (!loginForm.value.username.trim()) { |
| | | uni.showToast({ |
| | | title: "请输入用户名", |
| | | icon: "none", |
| | | duration: 2000, |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!loginForm.value.password.trim()) { |
| | | uni.showToast({ |
| | | title: "请输入密码", |
| | | icon: "none", |
| | | duration: 2000, |
| | | }); |
| | | return; |
| | | } |
| | | let userInfo = { |
| | | tenantId: "000000", |
| | | deptId: "", |
| | | roleId: "", |
| | | username: loginForm.value.username, |
| | | password: loginForm.value.password, |
| | | type: "account", |
| | | code: "", |
| | | key: "", |
| | | }; |
| | | |
| | | if (rememberPassword.value) { |
| | | uni.setStorageSync("rememberedUser", { |
| | | username: loginForm.value.username, |
| | | password: loginForm.value.password, |
| | | }); |
| | | } else { |
| | | uni.removeStorageSync("rememberedUser"); |
| | | } |
| | | |
| | | try { |
| | | const res = await loginByUsername( |
| | | userInfo.tenantId, |
| | | userInfo.deptId, |
| | | userInfo.roleId, |
| | | userInfo.username, |
| | | md5(userInfo.password), |
| | | userInfo.type, |
| | | userInfo.key, |
| | | userInfo.code |
| | | ); |
| | | userStore.setUserInfo(res.data); |
| | | uni.reLaunch({ |
| | | url: "/pages/map/index", |
| | | }); |
| | | } catch (error) { |
| | | const errorMsg = |
| | | error.data?.error_description !== "Bad credentials" |
| | | ? error.data?.error_description |
| | | : "登录失败,请重试"; |
| | | uni.showToast({ |
| | | title: errorMsg, |
| | | icon: "none", |
| | | duration: 2000, |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // 从本地存储加载记住的密码 |
| | | onMounted(() => { |
| | | const savedUserInfo = uni.getStorageSync("rememberedUser"); |
| | | console.log("记住密码", savedUserInfo); |
| | | if (savedUserInfo) { |
| | | loginForm.value.username = savedUserInfo.username; |
| | | loginForm.value.password = savedUserInfo.password; |
| | | rememberPassword.value = true; |
| | | } |
| | | }); |
| | | onLoad((options) => { |
| | | if (options.redirect && removeQueryString(options.redirect) !== LOGIN_PATH) { |
| | | redirect = decodeURIComponent(options.redirect); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .login-form-wrap { |
| | | position: relative; |
| | | text-align: center; |
| | | height: 100%; |
| | | width: 100%; |
| | | |
| | | .logo { |
| | | width: 127px; |
| | | height: 51px; |
| | | margin: 0 auto; |
| | | margin-top: 104px; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .lowerRightCorner { |
| | | position: absolute; |
| | | right: 0; |
| | | bottom: 0; |
| | | width: 425.61rpx; |
| | | height: 316.46rpx; |
| | | } |
| | | |
| | | .title { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | font-weight: 400; |
| | | font-size: 84rpx; |
| | | line-height: 82rpx; |
| | | letter-spacing: 1px; |
| | | text-shadow: 0px 8px 8px rgba(0, 0, 0, 0.18); |
| | | text-align: center; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | color: #1452d3; |
| | | text-align: center; |
| | | margin-bottom: 168rpx; |
| | | } |
| | | |
| | | .user-name, |
| | | .pass-word { |
| | | display: flex; |
| | | //justify-content: center; |
| | | align-items: center; |
| | | margin-left: 62rpx; |
| | | margin-right: 58rpx; |
| | | height: 118rpx; |
| | | border-bottom: 2rpx solid #e3e3e3; |
| | | |
| | | image { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | margin-right: 12rpx; |
| | | } |
| | | |
| | | :deep(uni-input) { |
| | | height: 40rpx; |
| | | line-height: 40rpx; |
| | | width: 80%; |
| | | margin-top: 20rpx; |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | :deep(input) { |
| | | height: 40rpx; |
| | | line-height: 40rpx; |
| | | width: 80%; |
| | | margin-top: 20rpx; |
| | | padding: 0 !important; |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | :deep(.uni-input-placeholder) { |
| | | font-size: 32rpx; |
| | | color: #e3e3e3; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .remember-password { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | margin-left: 62rpx; |
| | | margin-right: 58rpx; |
| | | margin-top: 20rpx; |
| | | |
| | | color: #666; |
| | | font-size: 28rpx; |
| | | |
| | | label { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | |
| | | input { |
| | | @apply pb-6rpx mb-10rpx text-left; |
| | | } |
| | | |
| | | .tips { |
| | | @apply mt-8rpx mb-60rpx; |
| | | color: $u-info; |
| | | } |
| | | |
| | | .login-btn { |
| | | z-index: 1; |
| | | @apply flex items-center justify-center py-12rpx px-0 text-30rpx border-none; |
| | | background: #1d6fe9; |
| | | color: white; |
| | | width: 590rpx; |
| | | height: 76rpx; |
| | | border-radius: 40rpx 40rpx 40rpx 40rpx; |
| | | margin-top: 100rpx; |
| | | |
| | | &::after { |
| | | @apply border-none; |
| | | } |
| | | } |
| | | |
| | | .alternative { |
| | | @apply flex justify-between mt-30rpx; |
| | | color: $u-tips-color; |
| | | } |
| | | } |
| | | |
| | | .login-type-wrap { |
| | | @apply flex justify-between pt-350rpx px-150rpx pb-150rpx; |
| | | |
| | | .item { |
| | | @apply flex items-center flex-col text-28rpx; |
| | | color: $u-content-color; |
| | | } |
| | | } |
| | | |
| | | .hint { |
| | | @apply px-40rpx py-20rpx text-24rpx; |
| | | color: $u-tips-color; |
| | | |
| | | .link { |
| | | color: $u-warning; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="panel-container" :style="{ |
| | | transform: `translateY(${translateY}px)`, |
| | | transition: isDragging ? 'none' : 'transform 0.3s ease', |
| | | }" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd"> |
| | | <!-- 顶部拖拽提示条 --> |
| | | <view class="drag-bar"></view> |
| | | |
| | | <!-- 搜索框(带毛玻璃) --> |
| | | <view class="search-box" :style="searchBoxStyle"> |
| | | <slot name="searchBox"></slot> |
| | | </view> |
| | | |
| | | <!-- 内容区 --> |
| | | <scroll-view scroll-y class="panel-content"> |
| | | <view class="dummy-content"> |
| | | <text>这里可以放搜索结果、推荐地点等内容</text> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | ref, |
| | | computed, |
| | | onMounted, |
| | | watch |
| | | } from 'vue' |
| | | |
| | | const props = defineProps({ |
| | | isSelectInput: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | searchVal: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | }) |
| | | |
| | | // 获取屏幕高度 |
| | | let screenHeight = 0 |
| | | |
| | | // 拖拽状态 |
| | | const startY = ref(0) |
| | | const currentY = ref(0) |
| | | const translateY = ref(0) |
| | | const isDragging = ref(false) |
| | | |
| | | const initialPosition = ref(0.8) |
| | | const oneSlidePosition = ref(0.6) |
| | | const twoSlidePosition = ref(0.1) |
| | | |
| | | // 毛玻璃效果 |
| | | const searchBoxStyle = computed(() => { |
| | | return translateY.value <= screenHeight * oneSlidePosition.value ? |
| | | { |
| | | backdropFilter: 'blur(10px)', |
| | | background: 'rgba(255, 255, 255, 0.7)', |
| | | } : |
| | | { |
| | | background: '#fff', |
| | | } |
| | | }) |
| | | |
| | | watch([ |
| | | () => props.isSelectInput, |
| | | () => props.searchVal, |
| | | ], ([newIsSelectInput, newSearchVal]) => { |
| | | if (newIsSelectInput) { |
| | | translateY.value = screenHeight * twoSlidePosition.value |
| | | } |
| | | |
| | | if (!newIsSelectInput && !newSearchVal) { |
| | | translateY.value = screenHeight * initialPosition.value |
| | | } |
| | | }) |
| | | |
| | | // 获取屏幕高度 |
| | | onMounted(() => { |
| | | const info = uni.getSystemInfoSync() |
| | | screenHeight = info.windowHeight |
| | | |
| | | // #ifdef APP-PLUS |
| | | initialPosition.value = 0.8 |
| | | // #endif |
| | | |
| | | // #ifdef H5 |
| | | initialPosition.value = 0.95 |
| | | |
| | | if (screenHeight < 500) { |
| | | initialPosition.value = 0.86 |
| | | } |
| | | |
| | | if (screenHeight > 575) { |
| | | initialPosition.value = 0.85 |
| | | } |
| | | |
| | | if (screenHeight > 642) { |
| | | initialPosition.value = 0.865 |
| | | } |
| | | // #endif |
| | | |
| | | translateY.value = screenHeight * initialPosition.value |
| | | }) |
| | | |
| | | // 拖拽开始 |
| | | const onTouchStart = (e) => { |
| | | // 只在拖拽时,阻止页面滚动 |
| | | startY.value = e.touches[0].clientY |
| | | currentY.value = translateY.value |
| | | isDragging.value = true |
| | | } |
| | | |
| | | // 拖拽移动 |
| | | const onTouchMove = (e) => { |
| | | // 只在拖拽时,阻止页面滚动 |
| | | if (isDragging.value) { |
| | | e.preventDefault() // 阻止滚动行为 |
| | | e.stopPropagation() // 阻止事件冒泡 |
| | | } |
| | | |
| | | const delta = e.touches[0].clientY - startY.value |
| | | let nextY = currentY.value + delta |
| | | |
| | | // 限制拖拽范围 [0, 90% 屏幕高度] |
| | | nextY = Math.min(screenHeight * (1 - twoSlidePosition.value), Math.max(0, nextY)) |
| | | |
| | | translateY.value = nextY |
| | | } |
| | | |
| | | // 拖拽结束后自动吸附 |
| | | const onTouchEnd = () => { |
| | | isDragging.value = false |
| | | const percentFromTop = 100 - (translateY.value / screenHeight) * 100 |
| | | |
| | | if (percentFromTop < 20) translateY.value = screenHeight * initialPosition.value |
| | | else if (percentFromTop < 40) translateY.value = screenHeight * oneSlidePosition.value |
| | | else if (percentFromTop < 75) translateY.value = screenHeight * oneSlidePosition.value |
| | | else if (percentFromTop < 90) translateY.value = screenHeight * twoSlidePosition.value |
| | | else translateY.value = screenHeight * twoSlidePosition.value |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .panel-container { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | width: 100%; |
| | | height: 90vh; |
| | | background: #fff; |
| | | border-top-left-radius: 20rpx; |
| | | border-top-right-radius: 20rpx; |
| | | box-shadow: 0 -4rpx 12rpx rgba(0, 0, 0, 0.15); |
| | | display: flex; |
| | | flex-direction: column; |
| | | z-index: 997; |
| | | touch-action: none; |
| | | /* 禁止默认的滚动行为 */ |
| | | } |
| | | |
| | | .drag-bar { |
| | | width: 80rpx; |
| | | height: 8rpx; |
| | | background: #ccc; |
| | | border-radius: 4rpx; |
| | | margin: 16rpx auto; |
| | | } |
| | | |
| | | .search-box { |
| | | padding: 0 24rpx; |
| | | margin-bottom: 12rpx; |
| | | border-radius: 40rpx; |
| | | transition: backdrop-filter 0.3s ease, background 0.3s ease; |
| | | } |
| | | |
| | | .search-input { |
| | | width: 100%; |
| | | height: 80rpx; |
| | | border-radius: 40rpx; |
| | | background: #f2f2f2; |
| | | padding: 0 24rpx; |
| | | font-size: 28rpx; |
| | | border: none; |
| | | outline: none; |
| | | } |
| | | |
| | | .panel-content { |
| | | flex: 1; |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .dummy-content { |
| | | text-align: center; |
| | | color: #999; |
| | | margin-top: 100rpx; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- |
| | | * @Author : yuan |
| | | * @Date : 2025-12-03 14:20:57 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-20 16:49:02 |
| | | * @FilePath : \src\pages\map\index.vue |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-12-03 14:20:57 |
| | | --> |
| | | <template> |
| | | <view class="page-wrap"> |
| | | <WebViewPlus :src="`${viewUrl}`" @webMessage="onPostMessage" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getWebViewUrl } from "@/utils/index.js"; |
| | | import WebViewPlus from "@/components/WebViewPlus.vue"; |
| | | import { onHide, onShow } from "@dcloudio/uni-app"; |
| | | // const viewUrl = getWebViewUrl("/defaultMap"); |
| | | |
| | | let envParam = ""; |
| | | // #ifdef WEB |
| | | envParam = "true"; |
| | | // #endif |
| | | // #ifdef APP-PLUS |
| | | envParam = "false"; |
| | | // #endif |
| | | |
| | | const updateKey = ref(0); |
| | | const viewUrl = computed(() => { |
| | | return getWebViewUrl("/defaultMap", { |
| | | isWeb: envParam, |
| | | updateKey: updateKey.value, |
| | | }); |
| | | }); |
| | | |
| | | const onPostMessage = (data) => { |
| | | // #ifdef MP-WEIXIN |
| | | if (data.type === "scanCode") { |
| | | } else if (data.type === "jumpAddWork") { |
| | | } else if (data.type === "jumpMapNav") { |
| | | //事件导航 |
| | | } else if (data.type === "workid") { |
| | | //事件详情 |
| | | } |
| | | // #endif |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | if (data.type === "scanCode") { |
| | | uni.navigateTo({ |
| | | url: "/subPackages/qrCode/index", |
| | | }); |
| | | } else if (data.type === "jumpAddWork") { |
| | | //新建任务 |
| | | const encodedData = encodeURIComponent(JSON.stringify(data.rowItem)); |
| | | uni.setStorageSync("webview_params", encodedData); |
| | | uni.navigateTo({ |
| | | url: `/subPackages/taskDetail/addTask/index`, |
| | | }); |
| | | } else if (data.type === "jumpMapNav") { |
| | | //事件导航 |
| | | uni.navigateTo({ |
| | | url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`, |
| | | }); |
| | | } else if (data.type === "workid") { |
| | | //事件详情 |
| | | uni.navigateTo({ |
| | | url: `/subPackages/workDetail/index?eventNum=${data.eventNum}`, |
| | | }); |
| | | } |
| | | // #endif |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // #ifndef MP-WEIXIN |
| | | |
| | | // #endif |
| | | }); |
| | | |
| | | onHide(() => { |
| | | updateKey.value = updateKey.value + 1; |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .page-wrap { |
| | | font-size: 20px; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 我的 --> |
| | | <template> |
| | | <view class="page-wrap"> |
| | | <view class="userBox"> |
| | | <view class="flex items-center pb-30rpx pl-30rpx pr-20rpx"> |
| | | <view class="mr-20rpx"> |
| | | <u-avatar :src="user.avatar" size="70" /> |
| | | </view> |
| | | <view class="flex-1"> |
| | | <view class="userName">{{ userStore?.userInfo?.nick_name }}</view> |
| | | <view class="departs"> |
| | | <image |
| | | src="https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/mobile.svg" |
| | | alt="" |
| | | /> |
| | | <span>{{ user.deptName }}</span> |
| | | </view> |
| | | </view> |
| | | <view class="rightLogo"> |
| | | <image |
| | | src="https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/logo2.png" |
| | | alt="" |
| | | /> |
| | | </view> |
| | | </view> |
| | | <view class="personalInformation"> |
| | | <div class="message"> |
| | | <div class="messagebox">个人信息</div> |
| | | <div class="editInfo" @click="handelEdit(1)"> |
| | | 点击编辑 |
| | | <image :src="rightImage" alt="" /> |
| | | </div> |
| | | </div> |
| | | <div class="passwordBox"> |
| | | <div class="messagebox">修改密码</div> |
| | | <div class="editInfo" @click="handelEdit(2)"> |
| | | 点击编辑 |
| | | <image :src="rightImage" alt="" /> |
| | | </div> |
| | | </div> |
| | | </view> |
| | | |
| | | <view class="mt-20rpx"> |
| | | <div class="goOutStyle" @click="logOut">退出登录</div> |
| | | </view> |
| | | <div class="bottomLogo"> |
| | | <image :src="logoImage" alt="" /> |
| | | </div> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getAssetsImage } from "@/utils/index.js"; |
| | | import { getUserInfo } from "@/api/user/index.js"; |
| | | import { useClipboard } from "@/hooks"; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { getDeviceRegionApi } from "@/api/map.js"; |
| | | |
| | | const { setClipboardData, getClipboardData } = useClipboard(); |
| | | |
| | | const rightImage = getAssetsImage("/images/user/rightBtn.svg"); |
| | | const logoImage = getAssetsImage("/images/user/logo1.png"); |
| | | |
| | | const userStore = useUserStore(); |
| | | const user = ref(""); |
| | | const getUserInfoData = () => { |
| | | getUserInfo().then((res) => { |
| | | user.value = res.data.data; |
| | | }); |
| | | }; |
| | | |
| | | function logOut() { |
| | | userStore.setUserInfo(null); |
| | | uni.reLaunch({ |
| | | url: "/pages/login/index", |
| | | }); |
| | | } |
| | | |
| | | function getDeviceRegion() { |
| | | getDeviceRegionApi().then((res) => {}); |
| | | } |
| | | const handelEdit = (val) => { |
| | | if (val === 1) { |
| | | uni.navigateTo({ |
| | | url: `/subPackages/userDetail/infos/index`, |
| | | }); |
| | | } else { |
| | | uni.navigateTo({ |
| | | url: `/subPackages/userDetail/password/index`, |
| | | }); |
| | | } |
| | | }; |
| | | onShow(() => { |
| | | getUserInfoData(); |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | |
| | | // #endif |
| | | }); |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .page-wrap { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | .userBox { |
| | | padding-top: 88rpx; |
| | | } |
| | | .userName { |
| | | font-weight: 700; |
| | | font-size: 36rpx; |
| | | color: #000000; |
| | | } |
| | | |
| | | .departs { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-top: 22rpx; |
| | | |
| | | image { |
| | | width: 28rpx; |
| | | height: 28rpx; |
| | | } |
| | | |
| | | span { |
| | | font-family: "Source Han Sans CN"; |
| | | font-weight: 400; |
| | | font-size: 28rpx; |
| | | color: rgba(0, 0, 0, 0.6); |
| | | margin-left: 6rpx; |
| | | } |
| | | } |
| | | |
| | | .rightLogo { |
| | | width: 200rpx; |
| | | height: 80rpx; |
| | | |
| | | image { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .bottomLogo { |
| | | position: absolute; |
| | | bottom: 50rpx; |
| | | left: 0; |
| | | right: 0; |
| | | margin: 0 auto; |
| | | text-align: center; |
| | | |
| | | image { |
| | | width: 128rpx; |
| | | height: 52rpx; |
| | | } |
| | | } |
| | | |
| | | .goOutStyle { |
| | | width: 590rpx; |
| | | height: 76rpx; |
| | | background: #1d6fe9; |
| | | border-radius: 40rpx; |
| | | font-family: "Source Han Sans CN"; |
| | | font-weight: 400; |
| | | font-size: 28rpx; |
| | | color: #ffffff; |
| | | text-align: center; |
| | | line-height: 76rpx; |
| | | margin: auto; |
| | | margin-top: 114rpx; |
| | | } |
| | | |
| | | .personalInformation { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 0 24rpx; |
| | | |
| | | .message, |
| | | .passwordBox { |
| | | width: 340rpx; |
| | | height: 160rpx; |
| | | |
| | | .messagebox { |
| | | padding: 20rpx 24rpx; |
| | | font-family: "Source Han Sans CN"; |
| | | font-weight: 500; |
| | | font-size: 28rpx; |
| | | color: #000000; |
| | | } |
| | | |
| | | .editInfo { |
| | | padding: 20rpx 24rpx; |
| | | color: rgba(0, 0, 0, 0.5); |
| | | font-family: "Source Han Sans CN"; |
| | | font-weight: 400; |
| | | font-size: 24rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | image { |
| | | width: 28rpx; |
| | | height: 28rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .message { |
| | | background: url(https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/info.png) |
| | | no-repeat center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | .passwordBox { |
| | | background: url(https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/password.png) |
| | | no-repeat center; |
| | | background-size: 100% 100%; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="eventTickets"> |
| | | 语音通话 |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup></script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .eventTickets { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="eventTickets"> |
| | | 工单 |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .eventTickets { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| New file |
| | |
| | | import setupI18n from "@/locales" |
| | | import setupStore from "@/store" |
| | | import setupRequest from "@/utils/request" |
| | | import setupPermission from "./permission" |
| | | import setupUI from "./ui" |
| | | |
| | | export default { |
| | | install (app) { |
| | | // UI扩展配置 |
| | | setupUI(app) |
| | | // 状态管理 |
| | | setupStore(app) |
| | | // 国际化 |
| | | setupI18n(app) |
| | | // 路由拦截 |
| | | setupPermission() |
| | | // 网络请求 |
| | | setupRequest() |
| | | } |
| | | } |
| New file |
| | |
| | | import { |
| | | ERROR404_PATH, |
| | | isPathExists, |
| | | LOGIN_PATH, |
| | | removeQueryString, |
| | | routes |
| | | } from "@/router" |
| | | import {useUserStore} from "@/store/index.js"; |
| | | |
| | | // 白名单路由 |
| | | const whiteList = ["/"] |
| | | routes.forEach(item => { |
| | | if (item.needLogin !== true) { |
| | | whiteList.push(item.path) |
| | | } |
| | | }) |
| | | |
| | | /** |
| | | * 权限校验 |
| | | * @param {string} path |
| | | * @returns {boolean} 是否有权限 |
| | | */ |
| | | export function hasPerm (path = "") { |
| | | if (!isPathExists(path) && path !== "/") { |
| | | uni.redirectTo({ |
| | | url: ERROR404_PATH |
| | | }) |
| | | return false |
| | | } |
| | | // 在白名单中或有token,直接放行 |
| | | const hasPermission = whiteList.includes(removeQueryString(path)) || useUserStore().$state.userInfo.access_token |
| | | if (!hasPermission) { |
| | | // 将用户的目标路径传递过去,这样可以实现用户登录之后,直接跳转到目标页面 |
| | | uni.redirectTo({ |
| | | url: `${LOGIN_PATH}?redirect=${encodeURIComponent(path)}` |
| | | }) |
| | | } |
| | | return hasPermission |
| | | } |
| | | |
| | | function setupPermission () { |
| | | // 注意:拦截uni.switchTab本身没有问题。但是在微信小程序端点击tabbar的底层逻辑并不是触发uni.switchTab。 |
| | | // 所以误认为拦截无效,此类场景的解决方案是在tabbar页面的页面生命周期onShow中处理。 |
| | | ;["navigateTo", "redirectTo", "reLaunch", "switchTab"].forEach(item => { |
| | | // https://uniapp.dcloud.net.cn/api/interceptor.html |
| | | uni.addInterceptor(item, { |
| | | // 页面跳转前进行拦截, invoke根据返回值进行判断是否继续执行跳转 |
| | | invoke (args) { |
| | | // args为所拦截api中的参数,比如拦截的是uni.redirectTo(OBJECT),则args对应的是OBJECT参数 |
| | | return hasPerm(args.url) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | export default setupPermission |
| New file |
| | |
| | | import uviewPlus, { |
| | | setConfig |
| | | } from "uview-plus" |
| | | |
| | | function setupUI(app) { |
| | | // 下面的在特殊场景下才需要配置,通常不用配置即可直接使用uview-plus框架。 |
| | | // 调用setConfig方法,方法内部会进行对象属性深度合并,可以放心嵌套配置 |
| | | // 需要在app.use(uview-plus)之后执行 |
| | | setConfig({ |
| | | // 修改$u.config对象的属性 |
| | | config: { |
| | | // 修改默认单位为rpx,相当于执行 uni.$u.config.unit = 'rpx' |
| | | unit: "rpx" |
| | | }, |
| | | // 修改$u.props对象的属性 |
| | | props: { |
| | | // 修改radio组件的size参数的默认值,相当于执行 uni.$u.props.radio.size = 30 |
| | | radio: { |
| | | // size: 20 |
| | | } |
| | | // 其他组件属性配置 |
| | | // ...... |
| | | } |
| | | }) |
| | | |
| | | app.use(uviewPlus, () => { |
| | | return { |
| | | options: { |
| | | // 修改config对象的属性 |
| | | config: { |
| | | customIcon: { |
| | | family: 'xyicon', |
| | | url: 'https://at.alicdn.com/t/c/font_5036193_7g86rzw8srl.ttf?t=1760003919145' |
| | | }, |
| | | customIcons: { |
| | | 'tuceng': '\uea2d', |
| | | 'dingwei': '\ue610', |
| | | }, |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export default setupUI |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:55:05 |
| | | * @FilePath : \src\router\index.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import pagesJson from "@/pages.json" |
| | | |
| | | // 路径常量 |
| | | export const HOME_PATH = "/pages/map/index" |
| | | export const LOGIN_PATH = "/pages/login/index" |
| | | export const ERROR404_PATH = "/pages/common/404/index" |
| | | |
| | | /** |
| | | * 解析路由地址 |
| | | * @param {object} pagesJson |
| | | * @returns [{"path": "/pages/tab/map/index","needLogin": false},...] |
| | | */ |
| | | function parseRoutes (pagesJson = {}) { |
| | | if (!pagesJson.pages) { |
| | | pagesJson.pages = [] |
| | | } |
| | | if (!pagesJson.subPackages) { |
| | | pagesJson.subPackages = [] |
| | | } |
| | | |
| | | function parsePages (pages = [], rootPath = "") { |
| | | const routes = [] |
| | | for (let i = 0; i < pages.length; i++) { |
| | | routes.push({ |
| | | path: rootPath ? `/${rootPath}/${pages[i].path}` : `/${pages[i].path}`, |
| | | needLogin: pages[i].needLogin === true |
| | | }) |
| | | } |
| | | return routes |
| | | } |
| | | |
| | | function parseSubPackages (subPackages = []) { |
| | | const routes = [] |
| | | for (let i = 0; i < subPackages.length; i++) { |
| | | routes.push(...parsePages(subPackages[i].pages, subPackages[i].root)) |
| | | } |
| | | return routes |
| | | } |
| | | |
| | | return [ |
| | | ...parsePages(pagesJson.pages), |
| | | ...parseSubPackages(pagesJson.subPackages) |
| | | ] |
| | | } |
| | | export const routes = parseRoutes(pagesJson) |
| | | |
| | | /** |
| | | * 当前路由 |
| | | * @returns {string} 当前路由 |
| | | */ |
| | | export function currentRoute () { |
| | | // getCurrentPages() 至少有1个元素,所以不再额外判断 |
| | | const pages = getCurrentPages() |
| | | const currentPage = pages[pages.length - 1] |
| | | return currentPage?.$page?.fullPath || currentPage.route |
| | | } |
| | | |
| | | /** |
| | | * 去除查询字符串 |
| | | * @param {string} path |
| | | * @returns {string} 去除查询字符串后的路径 |
| | | */ |
| | | export function removeQueryString (path = "") { |
| | | return path.split("?")[0] |
| | | } |
| | | |
| | | /** |
| | | * 路径是否存在 |
| | | * @param {string} path |
| | | * @returns {boolean} 路径是否存在 |
| | | */ |
| | | export function isPathExists (path = "") { |
| | | const cleanPath = removeQueryString(path) |
| | | return routes.some(item => item.path === cleanPath) |
| | | } |
| | | |
| | | /** |
| | | * 是否是tabbar页面路径 |
| | | * @param {string} path |
| | | * @returns {boolean} 是否是tabbar页面 |
| | | */ |
| | | export function isTabBarPath (path = "") { |
| | | const cleanPath = removeQueryString(path) |
| | | return ( |
| | | pagesJson.tabBar?.list?.some(item => `/${item.pagePath}` === cleanPath) === |
| | | true |
| | | ) |
| | | } |
| New file |
| | |
| | | @font-face { |
| | | font-family: "Source Han Sans CN"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/SourceHanSansCN-Regular.woff2") |
| | | format("opentype"); |
| | | font-weight: 400; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| | | |
| | | @font-face { |
| | | font-family: "Source Han Sans CN"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/SourceHanSansCN-Bold.woff2") |
| | | format("opentype"); |
| | | font-weight: 700; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| | | |
| | | @font-face { |
| | | font-family: "Segoe UI"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/SourceHanSansCN-Regular.woff2") |
| | | format("opentype"); |
| | | font-weight: 400; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| | | |
| | | @font-face { |
| | | font-family: "Segoe UI"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/SourceHanSansCN-Bold.woff2") |
| | | format("opentype"); |
| | | font-weight: 700; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| | | |
| | | /* 额外的标题字体 */ |
| | | @font-face { |
| | | font-family: "YouSheBiaoTiHei"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/YouSheBiaoTiHei.TTF") |
| | | format("truetype"); |
| | | font-weight: normal; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| New file |
| | |
| | | <svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316217"> |
| | | <g id="图标"> |
| | | <circle id="bg" cx="28" cy="28" r="25.5" fill="#1D6FE9" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | <g id="Frame"> |
| | | <path id="Vector" d="M29.051 17.3062C29.1972 17.3062 29.3373 17.3642 29.4407 17.4675C29.544 17.5709 29.6021 17.711 29.6021 17.8572V26.6735H38.4184C38.5645 26.6735 38.7047 26.7316 38.808 26.8349C38.9114 26.9382 38.9694 27.0784 38.9694 27.2245V28.3266C38.9694 28.4727 38.9114 28.6129 38.808 28.7162C38.7047 28.8195 38.5645 28.8776 38.4184 28.8776H29.6021V37.6939C29.6021 37.84 29.544 37.9802 29.4407 38.0835C29.3373 38.1869 29.1972 38.2449 29.051 38.2449H27.949C27.8029 38.2449 27.6627 38.1869 27.5594 38.0835C27.456 37.9802 27.398 37.84 27.398 37.6939V28.8776H18.5817C18.4355 28.8776 18.2954 28.8195 18.192 28.7162C18.0887 28.6129 18.0306 28.4727 18.0306 28.3266V27.2245C18.0306 27.0784 18.0887 26.9382 18.192 26.8349C18.2954 26.7316 18.4355 26.6735 18.5817 26.6735H27.398V17.8572C27.398 17.711 27.456 17.5709 27.5594 17.4675C27.6627 17.3642 27.8029 17.3062 27.949 17.3062H29.051Z" fill="white" stroke="white" stroke-width="0.4"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316217"> |
| | | <g id="图标"> |
| | | <circle id="bg" cx="28" cy="28" r="25.5" fill="#1D6FE9" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | <g id="Frame"> |
| | | <path id="Vector" d="M29.051 17.3062C29.1972 17.3062 29.3373 17.3642 29.4407 17.4675C29.544 17.5709 29.6021 17.711 29.6021 17.8572V26.6735H38.4184C38.5645 26.6735 38.7047 26.7316 38.808 26.8349C38.9114 26.9382 38.9694 27.0784 38.9694 27.2245V28.3266C38.9694 28.4727 38.9114 28.6129 38.808 28.7162C38.7047 28.8195 38.5645 28.8776 38.4184 28.8776H29.6021V37.6939C29.6021 37.84 29.544 37.9802 29.4407 38.0835C29.3373 38.1869 29.1972 38.2449 29.051 38.2449H27.949C27.8029 38.2449 27.6627 38.1869 27.5594 38.0835C27.456 37.9802 27.398 37.84 27.398 37.6939V28.8776H18.5817C18.4355 28.8776 18.2954 28.8195 18.192 28.7162C18.0887 28.6129 18.0306 28.4727 18.0306 28.3266V27.2245C18.0306 27.0784 18.0887 26.9382 18.192 26.8349C18.2954 26.7316 18.4355 26.6735 18.5817 26.6735H27.398V17.8572C27.398 17.711 27.456 17.5709 27.5594 17.4675C27.6627 17.3642 27.8029 17.3062 27.949 17.3062H29.051Z" fill="white" stroke="white" stroke-width="0.4"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316217"> |
| | | <g id="图标"> |
| | | <circle id="bg" cx="28" cy="28" r="25.5" fill="#1D6FE9" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | <g id="Frame"> |
| | | <path id="Vector" d="M29.051 17.3062C29.1972 17.3062 29.3373 17.3642 29.4407 17.4675C29.544 17.5709 29.6021 17.711 29.6021 17.8572V26.6735H38.4184C38.5645 26.6735 38.7047 26.7316 38.808 26.8349C38.9114 26.9382 38.9694 27.0784 38.9694 27.2245V28.3266C38.9694 28.4727 38.9114 28.6129 38.808 28.7162C38.7047 28.8195 38.5645 28.8776 38.4184 28.8776H29.6021V37.6939C29.6021 37.84 29.544 37.9802 29.4407 38.0835C29.3373 38.1869 29.1972 38.2449 29.051 38.2449H27.949C27.8029 38.2449 27.6627 38.1869 27.5594 38.0835C27.456 37.9802 27.398 37.84 27.398 37.6939V28.8776H18.5817C18.4355 28.8776 18.2954 28.8195 18.192 28.7162C18.0887 28.6129 18.0306 28.4727 18.0306 28.3266V27.2245C18.0306 27.0784 18.0887 26.9382 18.192 26.8349C18.2954 26.7316 18.4355 26.6735 18.5817 26.6735H27.398V17.8572C27.398 17.711 27.456 17.5709 27.5594 17.4675C27.6627 17.3642 27.8029 17.3062 27.949 17.3062H29.051Z" fill="white" stroke="white" stroke-width="0.4"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Frame" clip-path="url(#clip0_2193_2310)"> |
| | | <path id="Vector" d="M9.91638 3.74371C9.92985 3.74371 9.93856 3.74689 9.9447 3.75055V3.74957L14.1088 6.24371H14.1097C14.1278 6.25464 14.1342 6.27141 14.1342 6.28375V21.0543C14.134 21.0767 14.1164 21.0972 14.0883 21.0972C14.0819 21.0972 14.0745 21.0955 14.0677 21.0914L14.0658 21.0904L9.89587 18.5728L9.89294 18.5709L9.8783 18.5562C9.87433 18.5491 9.8725 18.5416 9.87244 18.5347V3.78766C9.87244 3.7637 9.8919 3.74371 9.91638 3.74371ZM7.17419 2.97223C7.18018 2.98303 7.18292 2.99144 7.18298 2.99957V18.3658C7.18293 18.3839 7.17326 18.3982 7.16052 18.4058L2.99451 20.897H2.99353C2.97355 20.909 2.94565 20.9043 2.93103 20.8804L2.92908 20.8775C2.92878 20.8769 2.92782 20.8752 2.92712 20.8726C2.92624 20.8693 2.92615 20.8639 2.92615 20.857V5.52887C2.92615 5.52001 2.92792 5.51161 2.93201 5.50446L2.94861 5.48785L7.1156 2.96051C7.13758 2.94718 7.16169 2.95431 7.17419 2.97223ZM21.0687 2.97321C21.0742 2.98351 21.0765 2.99172 21.0765 2.99957V18.3658C21.0765 18.3749 21.0746 18.3834 21.0707 18.3902L21.0551 18.4058L16.8881 20.897H16.8871C16.8671 20.9089 16.8392 20.9043 16.8246 20.8804L16.8236 20.8775L16.8217 20.8726C16.8208 20.8693 16.8197 20.8641 16.8197 20.857V5.53473C16.8199 5.52179 16.8226 5.51142 16.8265 5.50446C16.8303 5.4978 16.8359 5.49264 16.8422 5.48883L21.0092 2.96051C21.0316 2.9469 21.0565 2.9545 21.0687 2.97321Z" stroke="#8C8C8C" stroke-width="1.3"/> |
| | | </g> |
| | | <defs> |
| | | <clipPath id="clip0_2193_2310"> |
| | | <rect width="24" height="24" fill="white"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Frame" clip-path="url(#clip0_2193_2351)"> |
| | | <path id="Vector" d="M2.60857 4.9336L6.7781 2.40469C7.10623 2.20547 7.53279 2.3086 7.73201 2.63672C7.79763 2.74688 7.83279 2.8711 7.83279 3V18.3656C7.83279 18.6094 7.70622 18.8367 7.49529 18.9633L3.3281 21.4547C2.99998 21.6516 2.57341 21.5461 2.37419 21.2156C2.30857 21.1078 2.27576 20.9836 2.27576 20.857V5.52891C2.27576 5.28516 2.40232 5.06016 2.60857 4.9336ZM16.5047 4.9336L20.6719 2.40469C21 2.20547 21.4265 2.3086 21.6258 2.63672C21.6914 2.74688 21.7265 2.8711 21.7265 3V18.3656C21.7265 18.6094 21.6 18.8367 21.389 18.9633L17.2218 21.4547C16.8937 21.6516 16.4672 21.5461 16.2679 21.2156C16.2023 21.1078 16.1695 20.9836 16.1695 20.857V5.52891C16.1719 5.28516 16.2961 5.06016 16.5047 4.9336ZM10.2773 3.19219L14.4469 5.68829C14.6554 5.81485 14.7843 6.03985 14.7843 6.2836V21.0539C14.7843 21.4383 14.4726 21.7477 14.0883 21.7477C13.9617 21.7477 13.8375 21.7125 13.7297 21.6469L9.56013 19.1297C9.35154 19.0055 9.22263 18.7781 9.22263 18.5344V3.7875C9.22263 3.40313 9.53435 3.09375 9.91638 3.09375C10.0429 3.09375 10.1672 3.12657 10.2773 3.19219Z" fill="#1D6FE9"/> |
| | | </g> |
| | | <defs> |
| | | <clipPath id="clip0_2193_2351"> |
| | | <rect width="24" height="24" fill="white"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316224"> |
| | | <g id="Group 1321316110"> |
| | | <path id="Vector" d="M18.0517 2H5.9495C3.7748 2 2 3.95801 2 6.35412V16.6459C2 19.0469 3.77117 21 5.9495 21H18.0517C20.2264 21 22 19.042 22 16.6459V6.36023C22 3.95311 20.2288 2 18.0517 2ZM20.5502 16.6459C20.5502 18.2368 19.429 19.5315 18.0517 19.5315H5.9495C4.57098 19.5315 3.4498 18.2368 3.4498 16.6459V6.36023C3.4498 4.76935 4.57098 3.47462 5.9495 3.47462H18.0517C19.429 3.47462 20.5502 4.76935 20.5502 6.36023V16.6459Z" fill="#8C8C8C"/> |
| | | <path id="Vector_2" d="M9.5048 6.51704L7.3727 8.75839L6.45271 7.80389C6.38958 7.73887 6.31426 7.68693 6.23106 7.65102C6.14786 7.61512 6.0584 7.59595 5.96779 7.59461C5.87719 7.59328 5.7872 7.6098 5.70298 7.64324C5.61876 7.67668 5.54194 7.72639 5.47693 7.78951C5.41192 7.85264 5.35997 7.92795 5.32406 8.01116C5.28816 8.09436 5.26899 8.18382 5.26765 8.27442C5.26632 8.36503 5.28284 8.45502 5.31628 8.53924C5.34973 8.62346 5.39943 8.70027 5.46256 8.76529L6.88166 10.235C6.94604 10.3013 7.0231 10.354 7.10824 10.3899C7.19338 10.4259 7.28488 10.4444 7.37731 10.4443C7.4705 10.445 7.56288 10.4268 7.64885 10.3908C7.73483 10.3549 7.81263 10.3019 7.87756 10.235L10.5053 7.47499C10.6314 7.34231 10.6997 7.16497 10.695 6.98198C10.6904 6.79899 10.6133 6.62533 10.4806 6.49921C10.3479 6.3731 10.1706 6.30485 9.98757 6.30949C9.80458 6.31412 9.63092 6.39126 9.5048 6.52394V6.51704ZM17.3168 7.68314H12.3131C12.1301 7.68314 11.9546 7.75584 11.8252 7.88524C11.6958 8.01464 11.6231 8.19014 11.6231 8.37314C11.6231 8.55614 11.6958 8.73164 11.8252 8.86104C11.9546 8.99044 12.1301 9.06314 12.3131 9.06314H17.3168C17.4998 9.06314 17.6753 8.99044 17.8047 8.86104C17.9341 8.73164 18.0068 8.55614 18.0068 8.37314C18.0068 8.19014 17.9341 8.01464 17.8047 7.88524C17.6753 7.75584 17.4998 7.68314 17.3168 7.68314ZM17.3168 13.555H12.3131C12.1301 13.555 11.9546 13.6277 11.8252 13.7571C11.6958 13.8865 11.6231 14.062 11.6231 14.245C11.6231 14.428 11.6958 14.6035 11.8252 14.7329C11.9546 14.8623 12.1301 14.935 12.3131 14.935H17.3168C17.4998 14.935 17.6753 14.8623 17.8047 14.7329C17.9341 14.6035 18.0068 14.428 18.0068 14.245C18.0068 14.062 17.9341 13.8865 17.8047 13.7571C17.6753 13.6277 17.4998 13.555 17.3168 13.555ZM7.97875 11.4252C7.48997 11.4252 7.01216 11.5702 6.60575 11.8417C6.19934 12.1133 5.88258 12.4993 5.69553 12.9508C5.50848 13.4024 5.45953 13.8993 5.55489 14.3787C5.65025 14.8581 5.88562 15.2985 6.23125 15.6441C6.57687 15.9897 7.01722 16.2251 7.49662 16.3205C7.97601 16.4158 8.47292 16.3669 8.9245 16.1798C9.37608 15.9928 9.76205 15.676 10.0336 15.2696C10.3052 14.8632 10.4501 14.3854 10.4501 13.8966C10.4492 13.2414 10.1885 12.6134 9.72525 12.1501C9.26198 11.6868 8.63392 11.4262 7.97875 11.4252ZM7.97875 14.9902C7.76291 14.9902 7.55191 14.9262 7.37243 14.8063C7.19296 14.6864 7.05308 14.5159 6.97048 14.3165C6.88788 14.1171 6.86627 13.8977 6.90838 13.686C6.95049 13.4743 7.05443 13.2798 7.20705 13.1272C7.35968 12.9746 7.55414 12.8706 7.76584 12.8285C7.97754 12.7864 8.19698 12.808 8.3964 12.8906C8.59581 12.9732 8.76626 13.1131 8.88618 13.2926C9.0061 13.472 9.0701 13.683 9.0701 13.8989C9.06889 14.1877 8.95345 14.4644 8.74898 14.6684C8.54451 14.8725 8.26761 14.9873 7.97875 14.9879V14.9902Z" fill="#8C8C8C"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316223"> |
| | | <g id="Frame"> |
| | | <path id="Vector" d="M18.0517 2H5.9495C3.7748 2 2 3.95801 2 6.35412V16.6459C2 19.0469 3.77117 21 5.9495 21H18.0517C20.2264 21 22 19.042 22 16.6459V6.36023C22 3.95311 20.2288 2 18.0517 2ZM20.5502 16.6459C20.5502 18.2368 19.429 19.5315 18.0517 19.5315H5.9495C4.57098 19.5315 3.4498 18.2368 3.4498 16.6459V6.36023C3.4498 4.76935 4.57098 3.47462 5.9495 3.47462H18.0517C19.429 3.47462 20.5502 4.76935 20.5502 6.36023V16.6459Z" fill="#444444"/> |
| | | <path id="Exclude" d="M22 16.9C22 19.1644 20.1644 21 17.9 21H6.1C3.83563 21 2 19.1644 2 16.9V6.1C2 3.83563 3.83563 2 6.1 2H17.9C20.1644 2 22 3.83563 22 6.1V16.9ZM7.97852 11.4248C7.48981 11.4249 7.01181 11.5703 6.60547 11.8418C6.19916 12.1133 5.88233 12.4997 5.69531 12.9512C5.50838 13.4027 5.45935 13.8996 5.55469 14.3789C5.65006 14.8582 5.88585 15.2989 6.23145 15.6445C6.57702 15.99 7.01782 16.225 7.49707 16.3203C7.97634 16.4156 8.47335 16.3667 8.9248 16.1797C9.3762 15.9926 9.76171 15.6758 10.0332 15.2695C10.3048 14.8631 10.4502 14.3853 10.4502 13.8965C10.4493 13.2415 10.1886 12.6136 9.72559 12.1504C9.26232 11.6871 8.63368 11.4257 7.97852 11.4248ZM7.76562 12.8281C7.97733 12.786 8.19707 12.808 8.39648 12.8906C8.59587 12.9732 8.76584 13.1135 8.88574 13.293C9.00555 13.4723 9.07022 13.6828 9.07031 13.8984C9.0691 14.1872 8.95333 14.464 8.74902 14.668C8.54478 14.8718 8.268 14.9874 7.97949 14.9883C7.97895 14.9883 7.97852 14.9887 7.97852 14.9893C7.97852 14.9898 7.97808 14.9902 7.97754 14.9902C7.76211 14.99 7.5512 14.9263 7.37207 14.8066C7.19265 14.6867 7.05329 14.5158 6.9707 14.3164C6.88811 14.117 6.8661 13.8972 6.9082 13.6855C6.95036 13.474 7.05449 13.2795 7.20703 13.127C7.35961 12.9744 7.55403 12.8702 7.76562 12.8281ZM12.3135 13.5547C12.1305 13.5547 11.9546 13.6275 11.8252 13.7568C11.6958 13.8862 11.623 14.0621 11.623 14.2451C11.6231 14.4281 11.6958 14.604 11.8252 14.7334C11.9546 14.8627 12.1306 14.9346 12.3135 14.9346H17.3164C17.4993 14.9346 17.6753 14.8627 17.8047 14.7334C17.9341 14.604 18.0068 14.4281 18.0068 14.2451C18.0068 14.0621 17.9341 13.8862 17.8047 13.7568C17.6753 13.6275 17.4993 13.5547 17.3164 13.5547H12.3135ZM9.9873 6.30957C9.80571 6.31424 9.63341 6.3907 9.50759 6.52159C9.50661 6.5226 9.50488 6.52192 9.50488 6.52051C9.50488 6.5191 9.50316 6.51841 9.50219 6.51943L8.00092 8.09842C7.65871 8.45834 7.08544 8.46019 6.74091 8.10249L6.45312 7.80371C6.39011 7.73881 6.31447 7.68727 6.23145 7.65137C6.14824 7.61546 6.05838 7.59606 5.96777 7.59473C5.87718 7.59339 5.78734 7.61012 5.70312 7.64355C5.61892 7.67699 5.54157 7.72595 5.47656 7.78906C5.41165 7.85209 5.36012 7.9277 5.32422 8.01074C5.28831 8.09394 5.26891 8.18381 5.26758 8.27441C5.26624 8.36498 5.28299 8.45487 5.31641 8.53906C5.34985 8.62329 5.39976 8.70061 5.46289 8.76562L6.88184 10.2354C6.94617 10.3015 7.02337 10.3537 7.1084 10.3896C7.19343 10.4255 7.28466 10.4444 7.37695 10.4443C7.47005 10.445 7.56254 10.4265 7.64844 10.3906C7.73442 10.3547 7.813 10.3022 7.87793 10.2354L10.5049 7.47461C10.6309 7.34204 10.6998 7.16526 10.6953 6.98242C10.6907 6.79943 10.6131 6.62514 10.4805 6.49902C10.3478 6.373 10.1702 6.30494 9.9873 6.30957ZM12.3135 7.68359C12.1306 7.68359 11.9546 7.75551 11.8252 7.88477C11.6958 8.01414 11.6231 8.19008 11.623 8.37305C11.623 8.55605 11.6958 8.73193 11.8252 8.86133C11.9546 8.99064 12.1305 9.06348 12.3135 9.06348H17.3164C17.4993 9.06348 17.6753 8.99065 17.8047 8.86133C17.9341 8.73193 18.0068 8.55605 18.0068 8.37305C18.0068 8.19008 17.9341 8.01414 17.8047 7.88477C17.6753 7.7555 17.4993 7.68359 17.3164 7.68359H12.3135Z" fill="#1D6FE9"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="user"> |
| | | <g id="user_2"> |
| | | <path id="primary" d="M16 7C16 7.79113 15.7654 8.56448 15.3259 9.22228C14.8864 9.88008 14.2616 10.3928 13.5307 10.6955C12.7998 10.9983 11.9956 11.0775 11.2196 10.9231C10.4437 10.7688 9.73098 10.3878 9.17157 9.82843C8.61216 9.26902 8.2312 8.55629 8.07686 7.78036C7.92252 7.00444 8.00173 6.20017 8.30448 5.46927C8.60723 4.73836 9.11992 4.11365 9.77772 3.67412C10.4355 3.2346 11.2089 3 12 3C13.0609 3 14.0783 3.42143 14.8284 4.17157C15.5786 4.92172 16 5.93913 16 7ZM16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V19C4 19.5304 4.21071 20.0391 4.58579 20.4142C4.96086 20.7893 5.46957 21 6 21H18C18.5304 21 19.0391 20.7893 19.4142 20.4142C19.7893 20.0391 20 19.5304 20 19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15V15Z" stroke="#8C8C8C" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="user"> |
| | | <g id="user_2"> |
| | | <path id="primary" d="M16 7C16 7.79113 15.7654 8.56448 15.3259 9.22228C14.8864 9.88008 14.2616 10.3928 13.5307 10.6955C12.7998 10.9983 11.9956 11.0775 11.2196 10.9231C10.4437 10.7688 9.73098 10.3878 9.17157 9.82843C8.61216 9.26902 8.2312 8.55629 8.07686 7.78036C7.92252 7.00444 8.00173 6.20017 8.30448 5.46927C8.60723 4.73836 9.11992 4.11365 9.77772 3.67412C10.4355 3.2346 11.2089 3 12 3C13.0609 3 14.0783 3.42143 14.8284 4.17157C15.5786 4.92172 16 5.93913 16 7ZM16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19C4 19.5304 4.21071 20.0391 4.58579 20.4142C4.96086 20.7893 5.46957 21 6 21H18C18.5304 21 19.0391 20.7893 19.4142 20.4142C19.7893 20.0391 20 19.5304 20 19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15Z" fill="#1D6FE9" stroke="#1D6FE9" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316220"> |
| | | <g id="Group 1321316218"> |
| | | <path id="Vector" d="M21.9989 6.20825C21.9669 5.55338 21.6873 4.94449 21.2116 4.49381C20.7267 4.03439 20.0844 4 19.4034 4H16.7914L16.7915 2.79167C16.7915 2.5817 16.7037 2.38034 16.5474 2.23187C16.3911 2.08341 16.1792 2 15.9582 2C15.7372 2 15.5252 2.08341 15.3689 2.23187C15.2126 2.38034 15.1248 2.5817 15.1248 2.79167L15.1247 4H8.87489L8.87502 2.79167C8.87502 2.5817 8.78722 2.38034 8.63095 2.23187C8.47467 2.08341 8.26271 2 8.04169 2C7.82068 2 7.60872 2.08341 7.45244 2.23187C7.29616 2.38034 7.20837 2.5817 7.20837 2.79167L7.20823 4H4.60212C3.22092 4 2.07853 4.82277 2.00133 6.15213C2.0004 6.1667 2 6.18127 2 6.19583V18.5118C2 18.5263 2.0004 18.5408 2.00133 18.5555C2.076 19.841 3.16493 20.8908 4.53425 20.9973C4.55692 20.9992 4.57958 21 4.60238 21H19.4036C19.4263 21 19.4489 20.9991 19.4716 20.9973C20.1264 20.9455 20.7412 20.6768 21.2087 20.2381C21.6849 19.7916 21.9656 19.2105 21.9989 18.6021C21.9996 18.5884 22 18.5747 22 18.561V6.24498C21.9999 6.23273 21.9996 6.22048 21.9989 6.20825ZM20.3332 18.5368C20.2991 18.9766 19.8713 19.3641 19.3644 19.4167H4.64132C4.12625 19.3631 3.70439 18.9612 3.66666 18.4864V6.22079C3.70439 5.7392 4.11172 5.36465 4.60225 5.36465H7.20823V6.55215C7.20823 6.76211 7.29603 6.96347 7.45231 7.11194C7.60859 7.26041 7.82055 7.34381 8.04156 7.34381C8.26257 7.34381 8.47453 7.26041 8.63081 7.11194C8.78709 6.96347 8.87489 6.76211 8.87489 6.55215V5.36465H15.1248V6.55215C15.1248 6.76211 15.2126 6.96347 15.3689 7.11194C15.5252 7.26041 15.7372 7.34381 15.9582 7.34381C16.1792 7.34381 16.3911 7.26041 16.5474 7.11194C16.7037 6.96347 16.7915 6.76211 16.7915 6.55215V5.36465H19.4035C19.9032 5.36465 20.3004 5.75098 20.3332 6.26588V18.5368Z" fill="#8C8C8C"/> |
| | | <path id="Vector_2" d="M16.9465 13.9149H7.60278C7.38729 13.9149 7.18063 14.0005 7.02826 14.1529C6.87589 14.3053 6.79028 14.5119 6.79028 14.7274C6.79028 14.9429 6.87589 15.1496 7.02826 15.3019C7.18063 15.4543 7.38729 15.5399 7.60278 15.5399H16.9465C17.162 15.5399 17.3687 15.4543 17.5211 15.3019C17.6734 15.1496 17.759 14.9429 17.759 14.7274C17.759 14.5119 17.6734 14.3053 17.5211 14.1529C17.3687 14.0005 17.162 13.9149 16.9465 13.9149ZM7.5994 11.4774H12.0749C12.1812 11.4774 12.2864 11.4565 12.3846 11.4159C12.4827 11.3752 12.5719 11.3156 12.6471 11.2405C12.7222 11.1653 12.7818 11.0761 12.8225 10.978C12.8631 10.8798 12.8841 10.7746 12.884 10.6683V10.6615C12.884 10.5553 12.8631 10.4501 12.8224 10.3519C12.7818 10.2537 12.7222 10.1645 12.647 10.0894C12.5719 10.0143 12.4827 9.95467 12.3845 9.91401C12.2864 9.87335 12.1812 9.85242 12.0749 9.85242H7.5994C7.38481 9.85242 7.17901 9.93766 7.02727 10.0894C6.87553 10.2411 6.79028 10.4469 6.79028 10.6615V10.6683C6.79028 10.7746 6.81121 10.8798 6.85187 10.9779C6.89254 11.0761 6.95214 11.1653 7.02727 11.2404C7.1024 11.3156 7.1916 11.3752 7.28977 11.4158C7.38793 11.4565 7.49315 11.4774 7.5994 11.4774Z" fill="#8C8C8C"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316221"> |
| | | <g id="Group 1321316219"> |
| | | <path id="Vector" d="M21.9989 6.20825C21.9669 5.55338 21.6873 4.94449 21.2116 4.49381C20.7267 4.03439 20.0844 4 19.4034 4H16.7914L16.7915 2.79167C16.7915 2.5817 16.7037 2.38034 16.5474 2.23187C16.3911 2.08341 16.1792 2 15.9582 2C15.7372 2 15.5252 2.08341 15.3689 2.23187C15.2126 2.38034 15.1248 2.5817 15.1248 2.79167L15.1247 4H8.87489L8.87502 2.79167C8.87502 2.5817 8.78722 2.38034 8.63095 2.23187C8.47467 2.08341 8.26271 2 8.04169 2C7.82068 2 7.60872 2.08341 7.45244 2.23187C7.29616 2.38034 7.20837 2.5817 7.20837 2.79167L7.20823 4H4.60212C3.22092 4 2.07853 4.82277 2.00133 6.15213C2.0004 6.1667 2 6.18127 2 6.19583V18.5118C2 18.5263 2.0004 18.5408 2.00133 18.5555C2.076 19.841 3.16493 20.8908 4.53425 20.9973C4.55692 20.9992 4.57958 21 4.60238 21H19.4036C19.4263 21 19.4489 20.9991 19.4716 20.9973C20.1264 20.9455 20.7412 20.6768 21.2087 20.2381C21.6849 19.7916 21.9656 19.2105 21.9989 18.6021C21.9996 18.5884 22 18.5747 22 18.561V6.24498C21.9999 6.23273 21.9996 6.22048 21.9989 6.20825ZM20.3332 18.5368C20.2991 18.9766 19.8713 19.3641 19.3644 19.4167H4.64132C4.12625 19.3631 3.70439 18.9612 3.66666 18.4864V6.22079C3.70439 5.7392 4.11172 5.36465 4.60225 5.36465H7.20823V6.55215C7.20823 6.76211 7.29603 6.96347 7.45231 7.11194C7.60859 7.26041 7.82055 7.34381 8.04156 7.34381C8.26257 7.34381 8.47453 7.26041 8.63081 7.11194C8.78709 6.96347 8.87489 6.76211 8.87489 6.55215V5.36465H15.1248V6.55215C15.1248 6.76211 15.2126 6.96347 15.3689 7.11194C15.5252 7.26041 15.7372 7.34381 15.9582 7.34381C16.1792 7.34381 16.3911 7.26041 16.5474 7.11194C16.7037 6.96347 16.7915 6.76211 16.7915 6.55215V5.36465H19.4035C19.9032 5.36465 20.3004 5.75098 20.3332 6.26588V18.5368Z" fill="#1D6FE9"/> |
| | | <path id="Exclude" d="M19.5996 4C20.9251 4 22 5.07491 22 6.40039V18.5996C22 19.9251 20.9251 21 19.5996 21H4.40039C3.07491 21 2 19.9251 2 18.5996V6.40039C2 5.07491 3.07491 4 4.40039 4H19.5996ZM7.60254 13.915C7.38718 13.9151 7.18061 14.001 7.02832 14.1533C6.8761 14.3057 6.79004 14.5122 6.79004 14.7275C6.79007 14.9429 6.87605 15.1494 7.02832 15.3018C7.18061 15.454 7.38718 15.5399 7.60254 15.54H16.9463C17.1618 15.54 17.3691 15.4541 17.5215 15.3018C17.6737 15.1494 17.7588 14.9429 17.7588 14.7275C17.7588 14.5122 17.6736 14.3057 17.5215 14.1533C17.3691 14.0009 17.1618 13.915 16.9463 13.915H7.60254ZM7.59961 9.85254C7.38502 9.85254 7.17908 9.9381 7.02734 10.0898C6.87585 10.2415 6.79015 10.4468 6.79004 10.6611V10.668C6.79004 10.774 6.81103 10.8795 6.85156 10.9775C6.8922 11.0757 6.95227 11.1651 7.02734 11.2402C7.10248 11.3154 7.19187 11.3754 7.29004 11.416C7.38815 11.4566 7.49342 11.4775 7.59961 11.4775H12.0752C12.1814 11.4775 12.2866 11.4567 12.3848 11.416C12.4829 11.3754 12.5723 11.3154 12.6475 11.2402C12.7225 11.1651 12.7817 11.0756 12.8223 10.9775C12.8629 10.8794 12.8838 10.7741 12.8838 10.668V10.6611C12.8837 10.555 12.8629 10.4496 12.8223 10.3516C12.7817 10.2537 12.7223 10.1648 12.6475 10.0898C12.5724 10.0147 12.4829 9.95472 12.3848 9.91406C12.2866 9.87342 12.1814 9.85256 12.0752 9.85254H7.59961Z" fill="#1D6FE9"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | page { |
| | | font-size: $u-font-base; |
| | | color: $u-main-color; |
| | | background-color: $u-bg-color; |
| | | |
| | | height: 100%; |
| | | |
| | | } |
| New file |
| | |
| | | // 主题CSS变量 |
| | | :root, |
| | | page { |
| | | // 主色调 |
| | | --theme-primary: #21d59d; |
| | | --theme-success: #3ed268; |
| | | --theme-warning: #fe9831; |
| | | --theme-error: #fa4e62; |
| | | |
| | | // 文字颜色 |
| | | --theme-main-color: #1b233b; |
| | | --theme-content-color: #60687e; |
| | | --theme-tips-color: #7e869a; |
| | | --theme-light-color: #bdc3d2; |
| | | --theme-disabled-color: #dce0eb; |
| | | |
| | | // 背景颜色 |
| | | --theme-bg-color: #ffffff; |
| | | --theme-bg-color-secondary: #f8f9fa; |
| | | |
| | | // 边框颜色 |
| | | --theme-border-color: #e9ecef; |
| | | } |
| | | |
| | | .theme-dark { |
| | | // 主色调 |
| | | --theme-primary: #3c9cff; |
| | | --theme-success: #5ac725; |
| | | --theme-warning: #f9ae3d; |
| | | --theme-error: #f56c6c; |
| | | |
| | | // 文字颜色 |
| | | --theme-main-color: #ffffff; |
| | | --theme-content-color: #b0b8c1; |
| | | --theme-tips-color: #8a8f95; |
| | | --theme-light-color: #6c757d; |
| | | --theme-disabled-color: #495057; |
| | | |
| | | // 背景颜色 |
| | | --theme-bg-color: #1a1a1a; |
| | | --theme-bg-color-secondary: #2d2d2d; |
| | | } |
| | | |
| | | // 主题工具类 |
| | | .theme-bg { |
| | | background-color: var(--theme-bg-color); |
| | | } |
| | | |
| | | .theme-bg-secondary { |
| | | background-color: var(--theme-bg-color-secondary); |
| | | } |
| | | |
| | | .theme-text { |
| | | color: var(--theme-main-color); |
| | | } |
| | | |
| | | .theme-text-content { |
| | | color: var(--theme-content-color); |
| | | } |
| | | |
| | | .theme-text-tips { |
| | | color: var(--theme-tips-color); |
| | | } |
| New file |
| | |
| | | import { createPinia } from "pinia" |
| | | // pinia 持久化插件 |
| | | import { createPersistedState } from "pinia-plugin-persistedstate" |
| | | |
| | | // 导入子模块 |
| | | import useAppStore from "./modules/app" |
| | | import useUserStore from "./modules/user" |
| | | import useMapStore from "./modules/map" |
| | | |
| | | // 安装pinia状态管理插件 |
| | | function setupStore (app) { |
| | | const store = createPinia() |
| | | |
| | | const piniaPersist = createPersistedState({ |
| | | storage: { |
| | | getItem: uni.getStorageSync, |
| | | setItem: uni.setStorageSync |
| | | } |
| | | }) |
| | | store.use(piniaPersist) |
| | | |
| | | app.use(store) |
| | | } |
| | | |
| | | // 导出模块 |
| | | export { useAppStore, useUserStore, useMapStore } |
| | | export default setupStore |
| New file |
| | |
| | | import { defineStore } from 'pinia' |
| | | import storage from '@/utils/storage' |
| | | |
| | | // 缓存的主题 |
| | | const THEME_KEY = 'app-theme' |
| | | |
| | | const useAppStore = defineStore('app', { |
| | | state: () => ({ |
| | | systemInfo: {}, // 原本 TS: {} as UniApp.GetSystemInfoResult |
| | | theme: storage.get(THEME_KEY) || 'light', |
| | | deviceUpdateKey: 0, //设备刷新key |
| | | jobUpdateKey: 0, //任务刷新key |
| | | }), |
| | | getters: { |
| | | getSystemInfo (state) { |
| | | return state.systemInfo |
| | | }, |
| | | getTheme (state) { |
| | | return state.theme |
| | | } |
| | | }, |
| | | actions: { |
| | | setSystemInfo (info) { |
| | | this.systemInfo = info |
| | | }, |
| | | setDeviceUpdateKeyAdd () { |
| | | console.log(111, this.deviceUpdateKey + 1) |
| | | this.deviceUpdateKey = this.deviceUpdateKey + 1 |
| | | }, |
| | | setJobUpdateKeyAdd (state, data) { |
| | | this.deviceUpdateKey = this.deviceUpdateKey + 1 |
| | | }, |
| | | initSystemInfo () { |
| | | uni.getSystemInfo({ |
| | | success: (res) => { |
| | | this.setSystemInfo(res) |
| | | }, |
| | | fail: (err) => { |
| | | console.error(err) |
| | | } |
| | | }) |
| | | }, |
| | | /** |
| | | * 设置主题 |
| | | */ |
| | | setTheme (theme) { |
| | | this.theme = theme |
| | | // 保存到本地存储 |
| | | storage.set(THEME_KEY, this.theme) |
| | | }, |
| | | checkUpdate () { |
| | | const updateManager = uni.getUpdateManager() |
| | | updateManager.onCheckForUpdate((res) => { |
| | | // 请求完新版本信息的回调 |
| | | console.log(res.hasUpdate) |
| | | }) |
| | | updateManager.onUpdateReady(() => { |
| | | uni.showModal({ |
| | | title: '更新提示', |
| | | content: '新版本已经准备好,是否重启应用?', |
| | | success (res) { |
| | | if (res.confirm) { |
| | | // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 |
| | | updateManager.applyUpdate() |
| | | } |
| | | } |
| | | }) |
| | | }) |
| | | updateManager.onUpdateFailed((res) => { |
| | | console.error(res) |
| | | // 新的版本下载失败 |
| | | uni.showToast({ |
| | | title: '更新失败', |
| | | icon: 'error' |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | export default useAppStore |
| New file |
| | |
| | | import { |
| | | defineStore |
| | | } from 'pinia' |
| | | |
| | | const useMapStore = defineStore('map', { |
| | | state: () => ({ |
| | | selectMapLayerKey: 1 // 默认展示地图 |
| | | }), |
| | | actions: { |
| | | setSelectMapLayerKey(selectMapLayerKey) { |
| | | this.selectMapLayerKey = selectMapLayerKey |
| | | }, |
| | | }, |
| | | |
| | | getters: { |
| | | getSelectMapLayerKey(state) { |
| | | return state.selectMapLayerKey |
| | | }, |
| | | }, |
| | | |
| | | persist: true //持久化 |
| | | }) |
| | | |
| | | export default useMapStore |
| New file |
| | |
| | | import {defineStore} from 'pinia' |
| | | |
| | | const useUserStore = defineStore('user', { |
| | | state: () => ({ |
| | | userInfo: null // 用户信息 |
| | | }), |
| | | actions: { |
| | | setUserInfo(userInfo) { |
| | | this.userInfo = userInfo |
| | | }, |
| | | // 重置 |
| | | resetUserStore() { |
| | | this.$reset() |
| | | }, |
| | | // 合并 |
| | | mergeUserStore(data) { |
| | | this.$patch(data) |
| | | }, |
| | | }, |
| | | persist: true //持久化 |
| | | }) |
| | | |
| | | export default useUserStore |
| New file |
| | |
| | | <!-- |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-16 11:02:27 |
| | | * @FilePath : \src\subPackages\404\index.vue |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | --> |
| | | <template> |
| | | <div class="not-found"> |
| | | <u-navbar left-icon-size="40rpx" @left-click="handleBack" /> |
| | | <u-empty |
| | | mode="page" |
| | | text-size="20" |
| | | text="页面不存在" |
| | | :icon="errorImage" |
| | | width="380" |
| | | height="380" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getAssetsImage } from "@/utils/index.js"; |
| | | import { HOME_PATH } from "@/router"; |
| | | |
| | | const errorImage = getAssetsImage("/images/404.png"); |
| | | |
| | | function handleBack() { |
| | | uni.$u.route({ |
| | | type: "switchTab", |
| | | url: HOME_PATH, |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .not-found { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 100%; |
| | | overflow: auto; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 跳转第三方应用 --> |
| | | <template> |
| | | <view class="content"> |
| | | <!-- WebView组件 --> |
| | | <web-view :src="webViewUrl"></web-view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | webViewUrl: '' // WebView要加载的URL |
| | | }; |
| | | }, |
| | | onLoad(options) { |
| | | // 从导航参数中获取URL |
| | | if (options.url) { |
| | | this.webViewUrl = decodeURIComponent(options.url); |
| | | } else { |
| | | uni.showToast({ |
| | | title: '未获取到URL', |
| | | icon: 'none' |
| | | }); |
| | | // 如果没有URL,可以返回上一页或做其他处理 |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | .content { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <div class="avatarBox"> |
| | | <u-avatar @click="uploadAvatar" :src="userInfo.avatar" size="114" mode="aspectFill" /> |
| | | </div> |
| | | <view class="detailBox"> |
| | | <div class="detailCon"> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">姓名</div> |
| | | <div>{{userInfo.realName}}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">所属单位</div> |
| | | <div>{{userInfo.deptName}}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">手机号</div> |
| | | <u-input input-align="right" v-model="userInfo.phone" type="number" placeholder="请输入手机号" |
| | | class="input-item" /> |
| | | |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">邮箱</div> |
| | | <u-input input-align="right" v-model="userInfo.email" type="email" placeholder="请输入邮箱" |
| | | class="input-item" /> |
| | | </div> |
| | | </div> |
| | | </view> |
| | | <view class="btngroup"> |
| | | <u-button color="#AEAEAE" class="custom-style" shape="circle" @click="reset">重置</u-button> |
| | | <u-button color="#1D6FE9" class="custom-style" shape="circle" @click="submit">提交</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | getEnvObj, |
| | | getWebViewUrl |
| | | } from "@/utils/index.js"; |
| | | import { |
| | | getUserInfo, |
| | | updateInfo, |
| | | updatePassword |
| | | } from '@/api/user/index.js'; |
| | | import { |
| | | useUserStore |
| | | } from "@/store/index.js"; |
| | | const userInfo = ref({ |
| | | id: '', |
| | | avatar: '', |
| | | realName: '', |
| | | name: '', |
| | | phone: '', |
| | | email: '', |
| | | deptName: '', |
| | | }); |
| | | // 校验手机号 |
| | | const validatePhone = () => { |
| | | const phone = userInfo.value.phone |
| | | if (!phone) return true |
| | | const phoneRegex = /^1[3-9]\d{9}$/ |
| | | if (!phoneRegex.test(phone)) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入正确的手机号码', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false |
| | | } |
| | | return true |
| | | } |
| | | // 校验邮箱 |
| | | const validateEmail = () => { |
| | | if (!userInfo.value.email) return true |
| | | const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ |
| | | if (!emailRegex.test(userInfo.value.email)) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入正确的邮箱地址', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false |
| | | } |
| | | return true |
| | | } |
| | | const getUserInfoData = () => { |
| | | getUserInfo().then(res => { |
| | | const user = res.data.data; |
| | | userInfo.value = { |
| | | id: user.id, |
| | | avatar: user.avatar, |
| | | name: user.name, |
| | | realName: user.realName, |
| | | phone: user.phone, |
| | | email: user.email, |
| | | deptName: user.deptName, |
| | | }; |
| | | |
| | | }); |
| | | }; |
| | | const reset = () => { |
| | | getUserInfoData(); |
| | | }; |
| | | |
| | | const { |
| | | VITE_API_BASE_URL |
| | | } = getEnvObj() |
| | | |
| | | function uploadUtil(options) { |
| | | const { |
| | | formData, |
| | | filePath, |
| | | url |
| | | } = options; |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | let accessToken = useUserStore()?.$state?.userInfo?.access_token; |
| | | |
| | | uni.uploadFile({ |
| | | url: `${VITE_API_BASE_URL}${url}`, |
| | | name: 'file', |
| | | header: { |
| | | 'Blade-Auth': 'bearer ' + accessToken |
| | | }, |
| | | filePath: filePath, |
| | | formData, |
| | | success: (res) => { |
| | | const resData = JSON.parse(res.data) |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | resolve(res) |
| | | } else { |
| | | showToast(resData.message) |
| | | |
| | | reject(res) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | reject(err) |
| | | } |
| | | }); |
| | | }) |
| | | } |
| | | const uploadAvatar = () => { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | success: (res) => { |
| | | const tempFile = res.tempFiles[0]; // 获取文件对象 |
| | | const filePath = tempFile.path || tempFile.tempFilePath; |
| | | if (!filePath) { |
| | | uni.showToast({ |
| | | title: '获取文件路径失败', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | let fileName = tempFile.name; |
| | | if (!fileName) { |
| | | const pathWithoutProtocol = filePath.replace(/^file:\/\//, ''); |
| | | fileName = pathWithoutProtocol.split('/').pop() || 'unknown.png'; |
| | | } |
| | | |
| | | // 显示加载中 |
| | | uni.showLoading({ |
| | | title: '上传中...' |
| | | }); |
| | | |
| | | // 上传文件 |
| | | uploadUtil({ |
| | | filePath: filePath, |
| | | formData: { |
| | | fileName: fileName, |
| | | sn: 'avatar_upload' |
| | | }, |
| | | url: '/blade-resource/oss/endpoint/put-file' |
| | | }).then(res => { |
| | | const resData = JSON.parse(res.data); |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | // 更新头像显示 |
| | | userInfo.value.avatar = resData.data.link || resData.data.url; |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: '头像上传成功', |
| | | icon: 'success' |
| | | }); |
| | | } else { |
| | | throw new Error(resData.message || '上传失败'); |
| | | |
| | | } |
| | | }).catch(err => { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: err.message || '上传失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | const submit = () => { |
| | | if (!validatePhone() || !validateEmail()) return |
| | | userInfo.value.name = userInfo.value.realName; |
| | | updateInfo(userInfo.value).then(res => { |
| | | if (res.data.code === 200) { |
| | | uni.showToast({ |
| | | title: '修改信息成功', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | getUserInfoData() |
| | | |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg, |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | getUserInfoData() |
| | | } |
| | | |
| | | }); |
| | | |
| | | }; |
| | | onShow(async () => { |
| | | getUserInfoData() |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | .avatarBox { |
| | | width: 228rpx; |
| | | height: 228rpx; |
| | | margin: 76rpx 0; |
| | | } |
| | | |
| | | .detailBox { |
| | | width: 702rpx; |
| | | min-height: 430rpx; |
| | | background: #FFFFFF; |
| | | border-radius: 12rpx; |
| | | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | .detailCon { |
| | | padding: 0 24rpx; |
| | | } |
| | | |
| | | .orderRow { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 96rpx; |
| | | border-bottom: 2rpx solid #f5f5f5; |
| | | color: #7b7b7b; |
| | | |
| | | .rowTitle { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | ::v-deep .u-input { |
| | | border: none !important; |
| | | background: transparent !important; |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | ::v-deep .u-input__input { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | padding: 0 !important; |
| | | margin: 0 !important; |
| | | height: auto !important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .btngroup { |
| | | display: flex; |
| | | position: absolute; |
| | | bottom: 150rpx; |
| | | } |
| | | |
| | | :deep(.u-button:first-child) { |
| | | margin-right: 30rpx !important; |
| | | } |
| | | |
| | | .custom-style { |
| | | width: 276rpx; |
| | | height: 76rpx; |
| | | } |
| | | :deep(.u-button.data-v-461e713c){ |
| | | width: 276rpx !important; |
| | | height: 76rpx !important; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 修改密码 --> |
| | | <template> |
| | | <view class="container"> |
| | | <view class="detailBox"> |
| | | <div class="detailCon"> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">原始密码</div> |
| | | <input type="password" v-model="passwordForm.oldPassword" placeholder="请输入" class="input-item" /> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">新密码</div> |
| | | <input type="password" v-model="passwordForm.newPassword" placeholder="请输入" class="input-item" /> |
| | | |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">确认密码</div> |
| | | <input type="password" v-model="passwordForm.newPassword1" placeholder="请输入" class="input-item" /> |
| | | </div> |
| | | </div> |
| | | </view> |
| | | <view class="btngroup"> |
| | | <u-button color="#AEAEAE" class="custom-style" shape="circle" @click="reset">重置</u-button> |
| | | <u-button color="#1D6FE9" class="custom-style" shape="circle" @click="submit">提交</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | useUserStore |
| | | } from "@/store/index.js"; |
| | | import md5 from "js-md5"; |
| | | import { |
| | | getUserInfo, |
| | | updateInfo, |
| | | updatePassword |
| | | } from '@/api/user/index.js'; |
| | | const passwordIcon = { |
| | | show: 'fas fa-eye', // 显示密码时的图标 |
| | | hide: 'fas fa-eye-slash' // 隐藏密码时的图标 |
| | | } |
| | | const userStore = useUserStore(); |
| | | const passwordForm = ref({ |
| | | oldPassword: '', |
| | | newPassword: '', |
| | | newPassword1: '', |
| | | }); |
| | | // 校验密码不能包含中文 |
| | | const validatePasswordNoChinese = (password) => { |
| | | const chineseRegex = /[\u4e00-\u9fa5]/; |
| | | if (chineseRegex.test(password)) { |
| | | |
| | | uni.showToast({ |
| | | title: '密码不能包含中文字符', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false; |
| | | } |
| | | return true; |
| | | }; |
| | | // 校验密码复杂度(长度≥6位,包含字母和数字) |
| | | const validatePasswordStrength = (password) => { |
| | | if (password.length < 6) { |
| | | |
| | | uni.showToast({ |
| | | title: '密码长度不能少于6位', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false; |
| | | } |
| | | // const hasLetter = /[a-zA-Z]/.test(password); |
| | | // const hasNumber = /\d/.test(password); |
| | | // if (!hasLetter || !hasNumber) { |
| | | // ElMessage.error('密码需同时包含字母和数字'); |
| | | // return false; |
| | | // } |
| | | return true; |
| | | }; |
| | | const clearForm = () => { |
| | | passwordForm.value = { |
| | | oldPassword: '', |
| | | newPassword: '', |
| | | newPassword1: '', |
| | | }; |
| | | }; |
| | | const reset = () => { |
| | | clearForm(); |
| | | }; |
| | | const submit = () => { |
| | | // 原始密码校验 |
| | | if (!passwordForm.value.oldPassword) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入原始密码', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | // 中文校验 |
| | | if (!validatePasswordNoChinese(passwordForm.value.newPassword)) return; |
| | | // 新密码校验 |
| | | if (!passwordForm.value.newPassword) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入新密码', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | // 确认密码校验 |
| | | if (passwordForm.value.newPassword !== passwordForm.value.newPassword1) { |
| | | |
| | | uni.showToast({ |
| | | title: '两次输入的新密码不一致', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 复杂度校验 |
| | | if (!validatePasswordStrength(passwordForm.value.newPassword)) return; |
| | | updatePassword(md5(passwordForm.value.oldPassword), |
| | | md5(passwordForm.value.newPassword), |
| | | md5(passwordForm.value.newPassword1)).then(res => { |
| | | if (res.data.code === 200) { |
| | | uni.showToast({ |
| | | title: '修改信息成功', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | clearForm(); |
| | | userStore.setUserInfo(null) |
| | | uni.removeStorageSync('rememberedUser'); |
| | | uni.reLaunch({ |
| | | url: '/pages/login/index' |
| | | }) |
| | | |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg, |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | } |
| | | |
| | | }); |
| | | |
| | | }; |
| | | onShow(async () => { |
| | | clearForm(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detailBox { |
| | | margin-top: 40rpx; |
| | | width: 702rpx; |
| | | |
| | | min-height: 326rpx; |
| | | background: #FFFFFF; |
| | | border-radius: 12rpx; |
| | | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | .detailCon { |
| | | padding: 0 24rpx; |
| | | } |
| | | |
| | | .orderRow { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 96rpx; |
| | | border-bottom: 2rpx solid #f5f5f5; |
| | | color: #7b7b7b; |
| | | |
| | | |
| | | .rowTitle { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | input.input-item { |
| | | text-align: right; |
| | | border: none !important; |
| | | background: transparent !important; |
| | | box-shadow: none !important; |
| | | padding: 0 !important; |
| | | margin: 0 !important; |
| | | height: auto !important; |
| | | |
| | | outline: none; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | } |
| | | :deep(.uni-input-placeholder) { |
| | | color: #D5D5D5; |
| | | } |
| | | input.input-item::placeholder { |
| | | font-size: 30rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .btngroup { |
| | | display: flex; |
| | | position: absolute; |
| | | bottom: 150rpx; |
| | | } |
| | | |
| | | :deep(.u-button:first-child) { |
| | | margin-right: 30rpx !important; |
| | | } |
| | | |
| | | .custom-style { |
| | | width: 276rpx; |
| | | height: 76rpx; |
| | | } |
| | | :deep(.u-button.data-v-461e713c){ |
| | | width: 276rpx !important; |
| | | height: 76rpx !important; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- |
| | | * @Author : yuan |
| | | * @Date : 2025-11-13 18:14:52 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-20 16:56:27 |
| | | * @FilePath : \src\subPackages\workDetail\addWork\index.vue |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-11-13 18:14:52 |
| | | --> |
| | | <template> |
| | | <view> |
| | | <WebViewPlus |
| | | @webMessage="onPostMessage" |
| | | ref="sWebViewRef" |
| | | :src="`${viewUrl}`" |
| | | /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getWebViewUrl } from "@/utils/index.js"; |
| | | import WebViewPlus from "@/components/WebViewPlus.vue"; |
| | | const sWebViewRef = ref(null); |
| | | const viewUrl = getWebViewUrl("/addWork"); |
| | | |
| | | function onPostMessage(data) { |
| | | if (data.type === "submitSuccess") { |
| | | // #ifdef MP-WEIXIN |
| | | if ("fun" in data && data.fun === "add") { |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | } |
| | | // #endif |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | // uni.switchTab({ |
| | | // url: '/pages/work/index' |
| | | // }); |
| | | uni.switchTab({ |
| | | url: `/pages/work/index?addLog=111`, |
| | | }); |
| | | // #endif |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | <!-- 工单详情 - 包含待审核、待处理、处理中、已完成 --> |
| | | <template> |
| | | <div class="workDetailContainer"> |
| | | <WebViewPlus |
| | | ref="sWebViewRef" |
| | | :src="`${viewUrl}`" |
| | | @webMessage="onPostMessage" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getWebViewUrl } from "@/utils/index.js"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | const userStore = useUserStore(); |
| | | const userInfo = userStore.userInfo; |
| | | const sWebViewRef = ref(null); |
| | | const viewUrl = ref(""); |
| | | onLoad((options) => { |
| | | const eventNum = options.eventNum; |
| | | viewUrl.value = getWebViewUrl("/workDetail", { |
| | | eventNum: eventNum, |
| | | totalNum: options.totalNum, |
| | | keyword: options.keyword, |
| | | aiType: options.aiType, |
| | | wLJobInfoId: options.wLJobInfoId, |
| | | status: options.status, |
| | | current: options.current, |
| | | }); |
| | | }); |
| | | |
| | | function onPostMessage(data) { |
| | | if (data.type === "workback") { |
| | | // #ifdef MP-WEIXIN |
| | | if ("fun" in data && data.fun === "add") { |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | } |
| | | // #endif |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | uni.switchTab({ |
| | | url: `/pages/work/index?addLog=111`, |
| | | // url: '/pages/work/index' |
| | | }); |
| | | // #endif |
| | | } else if (data.type === "jumpMapNav") { |
| | | // #ifndef MP-WEIXIN |
| | | uni.navigateTo({ |
| | | url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`, |
| | | }); |
| | | // #endif |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .workDetailContainer { |
| | | width: 100%; |
| | | height: 100%; |
| | | background-size: cover; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- |
| | | * @Author : yuan |
| | | * @Date : 2025-10-22 14:59:10 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-19 14:52:54 |
| | | * @FilePath : \src\subPackages\workDetail\mapWork\index.vue |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-10-22 14:59:10 |
| | | --> |
| | | <!-- 地图展示 --> |
| | | <template> |
| | | <WebViewPlus |
| | | ref="sWebViewRef" |
| | | :src="`${viewUrl}`" |
| | | @webMessage="onPostMessage" |
| | | /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getWebViewUrl } from "@/utils/index.js"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | |
| | | const sWebViewRef = ref(null); |
| | | const viewUrl = ref(""); |
| | | |
| | | onLoad((options) => { |
| | | const currentItem = options.currentItem; |
| | | viewUrl.value = getWebViewUrl("/mapWork", { currentItem: currentItem }); |
| | | }); |
| | | function onPostMessage(data) { |
| | | // #ifdef MP-WEIXIN |
| | | // #endif |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | if (data.type === "workDetailback") { |
| | | // uni.navigateTo({ |
| | | // url: '/subPackages/workDetail/index' |
| | | // }); |
| | | uni.navigateBack({ |
| | | delta: 1, |
| | | }); |
| | | } |
| | | |
| | | if (data.type === "browser") { |
| | | uni.navigateTo({ |
| | | url: |
| | | "/subPackages/browser/index?url=" + encodeURIComponent(data.data.url), |
| | | }); |
| | | } |
| | | // #endif |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| New file |
| | |
| | | |
| | | <!-- 照片放大 --> |
| | | <template> |
| | | <view> |
| | | <WebViewPlus v-if="isApp" ref="sWebViewRef" :src="`${viewUrl}`" @webMessage="onPostMessage"/></view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {getWebViewUrl} from "@/utils/index.js"; |
| | | import { onLoad } from '@dcloudio/uni-app'; |
| | | const viewUrl = ref('') |
| | | onLoad( (options) => { |
| | | const eventNum= options.eventNum; |
| | | viewUrl.value = getWebViewUrl('/photoMagnify', {eventNum:eventNum}) |
| | | }); |
| | | const isApp = ref(false) |
| | | onShow(() => { |
| | | isApp.value = true |
| | | }); |
| | | |
| | | onHide(() => { |
| | | isApp.value = false |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| New file |
| | |
| | | @import 'uview-plus/theme.scss'; |
| | | @import '@/static/styles/theme.scss'; |
| | | |
| | | /* 颜色变量 - 使用CSS变量支持主题切换 */ |
| | | |
| | | /* 行为相关颜色 */ |
| | | $u-primary: var(--theme-primary); |
| | | $u-primary-dark: var(--theme-primary-dark); |
| | | $u-success: var(--theme-success); |
| | | $u-warning: var(--theme-warning); |
| | | $u-error: var(--theme-error); |
| | | |
| | | /* 文字基本颜色 */ |
| | | $u-main-color: var(--theme-main-color); |
| | | $u-content-color: var(--theme-content-color); |
| | | $u-tips-color: var(--theme-tips-color); |
| | | $u-light-color: var(--theme-light-color); |
| | | $u-disabled-color: var(--theme-disabled-color); |
| | | |
| | | /* 背景颜色 */ |
| | | $u-bg-color: var(--theme-bg-color); |
| | | |
| | | /* 边框颜色 */ |
| | | $u-border-color: var(--theme-border-color); |
| | | |
| | | /* 尺寸变量 */ |
| | | |
| | | /* 文字尺寸 */ |
| | | $u-font-sm: 24rpx; |
| | | $u-font-base: 28rpx; |
| | | $u-font-lg: 32rpx; |
| | | |
| | | /* 图片尺寸 */ |
| | | $u-img-sm: 40rpx; |
| | | $u-img-base: 52rpx; |
| | | $u-img-lg: 80rpx; |
| | | |
| | | /* Border Radius */ |
| | | $u-border-radius-sm: 4rpx; |
| | | $u-border-radius-base: 6rpx; |
| | | $u-border-radius-lg: 12rpx; |
| | | $u-border-radius-circle: 50%; |
| | | |
| | | /* 水平间距 */ |
| | | $u-spacing-row-sm: 10rpx; |
| | | $u-spacing-row-base: 20rpx; |
| | | $u-spacing-row-lg: 30rpx; |
| | | |
| | | /* 垂直间距 */ |
| | | $u-spacing-col-sm: 8rpx; |
| | | $u-spacing-col-base: 16rpx; |
| | | $u-spacing-col-lg: 24px; |
| | | |
| | | /* 透明度 */ |
| | | $u-opacity-disabled: 0.3; |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-10-15 15:52:12 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-17 14:09:14 |
| | | * @FilePath : \src\utils\common\index.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-10-15 15:52:12 |
| | | */ |
| | | // 小程序更新检测 |
| | | import { useUserStore } from "@/store/index.js" |
| | | import configEnv from "@/config/env.js" |
| | | import process from "node:process" |
| | | |
| | | export function mpUpdate () { |
| | | const updateManager = uni.getUpdateManager() |
| | | updateManager.onCheckForUpdate(res => { |
| | | // 请求完新版本信息的回调 |
| | | console.log(res.hasUpdate) |
| | | }) |
| | | updateManager.onUpdateReady(() => { |
| | | uni.showModal({ |
| | | title: "更新提示", |
| | | content: "检测到新版本,是否下载新版本并重启小程序?", |
| | | success (res) { |
| | | if (res.confirm) { |
| | | // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 |
| | | updateManager.applyUpdate() |
| | | } |
| | | } |
| | | }) |
| | | }) |
| | | updateManager.onUpdateFailed(() => { |
| | | // 新的版本下载失败 |
| | | uni.showModal({ |
| | | title: "已经有新版本了哟~", |
| | | content: "新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~", |
| | | showCancel: false |
| | | }) |
| | | }) |
| | | } |
| | | export function getStatusBarHeight () { |
| | | try { |
| | | const systemInfo = uni.getWindowInfo() |
| | | |
| | | // #ifdef APP-PLUS |
| | | return systemInfo.statusBarHeight || 0 |
| | | // #endif |
| | | |
| | | // #ifdef MP-WEIXIN |
| | | return 0 |
| | | // #endif |
| | | |
| | | // #ifdef H5 |
| | | return systemInfo.statusBarHeight || 0 |
| | | // #endif |
| | | return systemInfo.statusBarHeight || 0 |
| | | } catch (error) { |
| | | return 0 |
| | | } |
| | | } |
| | | export function getEnvObj () { |
| | | return configEnv[__APP_ENV__?.ENV_NAME] || {} |
| | | } |
| | | |
| | | export function getWebViewUrl (targetUrl, otherParams) { |
| | | const userStore = useUserStore() |
| | | const url = getEnvObj().VITE_APP_WEBVIEW_URL |
| | | const uniPlatform = __APP_ENV__.UNI_PLATFORM |
| | | const statusBarHeight = getStatusBarHeight() |
| | | // 1. 处理用户参数 |
| | | const userParams = userStore?.userInfo ? JSON.stringify(userStore.userInfo) : '{}' |
| | | // 2. 构建查询参数字符串 |
| | | let queryString = `params=${encodeURIComponent(userParams)}&topMargin=${statusBarHeight}&uniPlatform=${uniPlatform}` |
| | | |
| | | // 3. 处理 otherParams 对象 |
| | | if (otherParams && typeof otherParams === 'object') { |
| | | Object.keys(otherParams).forEach(key => { |
| | | const value = otherParams[key] |
| | | if (value !== undefined && value !== null) { |
| | | queryString += `&${key}=${encodeURIComponent(value)}` |
| | | } |
| | | }) |
| | | } |
| | | // 4. 拼接完整 URL |
| | | return `${url}${targetUrl}?${queryString}` |
| | | } |
| | | |
| | | export function getAssetsImage (targetUrl) { |
| | | const url = getEnvObj().VITE_APP_ASSETS_URL |
| | | return `${url}${targetUrl}` |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 10:07:13 |
| | | * @FilePath : \src\utils\index.ts |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | export * from "./common" |
| | | export * from "./modals" |
| | | export * from "./request" |
| | | export * from "./storage" |
| New file |
| | |
| | | /** |
| | | * 轻提示 |
| | | * @param {string} content 提示内容 |
| | | * @param {object} option 配置 |
| | | */ |
| | | export function Toast (content, option = {}) { |
| | | uni.showToast({ |
| | | title: content, |
| | | icon: "none", |
| | | mask: true, |
| | | duration: 1500, |
| | | ...option |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * Loading 提示框 |
| | | * @param {string} content 提示内容 |
| | | */ |
| | | export const Loading = { |
| | | show: (content = "加载中") => { |
| | | uni.showLoading({ |
| | | title: content, |
| | | mask: true |
| | | }) |
| | | }, |
| | | hide: () => { |
| | | uni.hideLoading() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Dialog 提示框 |
| | | * @param {string} content 提示内容 |
| | | * @param {object} option 配置 |
| | | */ |
| | | export function Dialog (content, option = {}) { |
| | | option.showCancel = false |
| | | return new Promise((resolve, reject) => { |
| | | uni.showModal({ |
| | | title: "温馨提示", |
| | | content, |
| | | showCancel: false, |
| | | confirmColor: "#1677FF", |
| | | success (res) { |
| | | if (res.confirm) resolve(res) |
| | | }, |
| | | fail () { |
| | | reject(new Error("Alert 调用失败 !")) |
| | | }, |
| | | ...option |
| | | }) |
| | | }) |
| | | } |
| New file |
| | |
| | | import Request from "uview-plus/libs/luch-request/index" |
| | | import { requestInterceptors, responseInterceptors } from "./interceptors" |
| | | import configEnv from "@/config/env.js"; |
| | | import {getEnvObj} from "@/utils/index.js"; |
| | | |
| | | const http = new Request() |
| | | |
| | | export function request (config) { |
| | | return new Promise((resolve, reject) => { |
| | | http |
| | | .request(config) |
| | | .then(res => { |
| | | resolve(res) |
| | | }) |
| | | .catch(err => { |
| | | reject(err) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 引入拦截器配置 |
| | | export function setupRequest () { |
| | | http.setConfig(defaultConfig => { |
| | | /* defaultConfig 为默认全局配置 */ |
| | | defaultConfig.baseURL = getEnvObj().VITE_API_BASE_URL |
| | | // #ifdef H5 |
| | | if (import.meta.env.VITE_APP_PROXY === "true") { |
| | | defaultConfig.baseURL = import.meta.env.VITE_API_PREFIX |
| | | } |
| | | // #endif |
| | | return defaultConfig |
| | | }) |
| | | requestInterceptors(http) |
| | | responseInterceptors(http) |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | export function get (url, config) { |
| | | return request({ ...config, url, method: "GET" }) |
| | | } |
| | | |
| | | export function post (url, config) { |
| | | return request({ ...config, url, method: "POST" }) |
| | | } |
| | | |
| | | export function upload (url, config) { |
| | | return request({ ...config, url, method: "UPLOAD" }) |
| | | } |
| | | |
| | | export function download (url, config) { |
| | | return request({ ...config, url, method: "DOWNLOAD" }) |
| | | } |
| | | |
| | | export default setupRequest |
| New file |
| | |
| | | import { |
| | | useUserStore |
| | | } from "@/store" |
| | | import storage from "@/utils/storage" |
| | | import { |
| | | showMessage |
| | | } from "./status" |
| | | import website from '@/config/website' |
| | | import { |
| | | Base64 |
| | | } from 'js-base64' |
| | | |
| | | // 防止重复提交 |
| | | const repeatSubmit = config => { |
| | | const requestObj = { |
| | | url: config.url, |
| | | data: typeof config.data === "object" ? |
| | | JSON.stringify(config.data) : config.data, |
| | | time: new Date().getTime() |
| | | } |
| | | const sessionObj = storage.getJSON("sessionObj") |
| | | if (!sessionObj) { |
| | | storage.setJSON("sessionObj", requestObj) |
| | | } else { |
| | | const s_url = sessionObj.url // 请求地址 |
| | | const s_data = sessionObj.data // 请求数据 |
| | | const s_time = sessionObj.time // 请求时间 |
| | | const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交 |
| | | if ( |
| | | s_data === requestObj.data && |
| | | requestObj.time - s_time < interval && |
| | | s_url === requestObj.url |
| | | ) { |
| | | const message = "数据正在处理,请勿重复提交" |
| | | console.warn(`[${s_url}]: ${message}`) |
| | | return Promise.reject(new Error(message)) |
| | | } else { |
| | | storage.setJSON("sessionObj", requestObj) |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 请求拦截器 |
| | | function requestInterceptors(http) { |
| | | |
| | | http.interceptors.request.use((config) => { |
| | | const {detail} = useUserStore().$state?.userInfo || {} |
| | | // 假设有token值需要在头部需要携带 |
| | | let accessToken = useUserStore()?.$state?.userInfo?.access_token; |
| | | if (accessToken) { |
| | | config.header['Blade-Auth'] = 'bearer ' + accessToken; |
| | | } |
| | | if (detail?.areaCode) { |
| | | config.header['areaCode'] = detail.areaCode |
| | | } |
| | | // 安全请求header |
| | | config.header['Blade-Requested-With'] = 'BladeHttpRequest'; |
| | | // 客户端认证参数 |
| | | config.header['Authorization'] = 'Basic ' + Base64.encode(website.clientId + ':' + website.clientSecret); |
| | | return config |
| | | }, config => { // 可使用async await 做异步操作 |
| | | return Promise.reject(config) |
| | | }) |
| | | } |
| | | |
| | | // 响应拦截器 |
| | | function responseInterceptors(http) { |
| | | http.interceptors.response.use((response) => { |
| | | let res = response |
| | | const status = res.data.error_code || res.data.code || res.statusCode |
| | | const message = res?.data?.msg || res?.data?.error_description || res?.data?.message || '系统错误' |
| | | if (status !== 200) { |
| | | uni.showToast({title: message, icon: 'none'}); |
| | | return Promise.reject(response); |
| | | } |
| | | return response; |
| | | }, (response) => { |
| | | let res = response |
| | | const message = res?.data?.msg || res?.data?.error_description || res?.data?.message || '系统错误' |
| | | /* 对响应错误做点什么 (statusCode !== 200)*/ |
| | | uni.showToast({title: message, icon: 'none'}); |
| | | if (response.statusCode === 401) { |
| | | const pages = getCurrentPages() |
| | | const currentPage = pages[pages.length - 1] |
| | | uni.reLaunch({ |
| | | url: `/pages/login/index?redirect=/${currentPage.route}` |
| | | }) |
| | | } |
| | | return Promise.reject(response) |
| | | }) |
| | | } |
| | | |
| | | export { |
| | | requestInterceptors, |
| | | responseInterceptors |
| | | } |
| New file |
| | |
| | | /** |
| | | * 根据状态码,生成对应的错误信息 |
| | | * @param {number|string} status 状态码 |
| | | * @returns {string} 错误信息 |
| | | */ |
| | | export const showMessage = status => { |
| | | let message = "" |
| | | switch (status) { |
| | | case 400: |
| | | message = "请求错误(400)" |
| | | break |
| | | case 401: |
| | | message = "未授权,请重新登录(401)" |
| | | break |
| | | case 403: |
| | | message = "拒绝访问(403)" |
| | | break |
| | | case 404: |
| | | message = "请求出错(404)" |
| | | break |
| | | case 408: |
| | | message = "请求超时(408)" |
| | | break |
| | | case 500: |
| | | message = "服务器错误(500)" |
| | | break |
| | | case 501: |
| | | message = "服务未实现(501)" |
| | | break |
| | | case 502: |
| | | message = "网络错误(502)" |
| | | break |
| | | case 503: |
| | | message = "服务不可用(503)" |
| | | break |
| | | case 504: |
| | | message = "网络超时(504)" |
| | | break |
| | | case 505: |
| | | message = "HTTP版本不受支持(505)" |
| | | break |
| | | default: |
| | | message = `连接出错(${status})!` |
| | | } |
| | | return `${message},请检查网络或联系管理员!` |
| | | } |
| New file |
| | |
| | | const storage = { |
| | | set (key, value) { |
| | | if (key !== null && value !== null) uni.setStorageSync(key, value) |
| | | }, |
| | | get (key) { |
| | | if (key === null) return null |
| | | |
| | | return uni.getStorageSync(key) |
| | | }, |
| | | setJSON (key, jsonValue) { |
| | | if (jsonValue !== null) this.set(key, JSON.stringify(jsonValue)) |
| | | }, |
| | | getJSON (key) { |
| | | const value = this.get(key) |
| | | if (value) return JSON.parse(value) |
| | | }, |
| | | remove (key) { |
| | | uni.removeStorageSync(key) |
| | | } |
| | | } |
| | | |
| | | export default storage |
| New file |
| | |
| | | import LibGenerateTestUserSig from './lib-generate-test-usersig-es.min.js'; |
| | | |
| | | const SDKAPPID = 1600112974; |
| | | const SECRETKEY = '45606bc613e715efb9ec9117fed1fef29411630018c65de7f7d3a5290e9c3b83'; |
| | | const EXPIRETIME = 604800; |
| | | |
| | | export function genTestUserSig(userID) { |
| | | const generator = new LibGenerateTestUserSig(SDKAPPID, SECRETKEY, EXPIRETIME); |
| | | const userSig = generator.genTestUserSig(userID); |
| | | |
| | | return { |
| | | SDKAppID: SDKAPPID, |
| | | SECRETKEY, |
| | | userSig, |
| | | }; |
| | | } |
| New file |
| | |
| | | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { |
| | | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } |
| | | return new (P || (P = Promise))(function (resolve, reject) { |
| | | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } |
| | | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } |
| | | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } |
| | | step((generator = generator.apply(thisArg, _arguments || [])).next()); |
| | | }); |
| | | }; |
| | | import { NAME } from './constants.js'; |
| | | import { TRTCRoleType, TRTCAudioQuality, TRTCVideoRotation, TRTCVideoFillMode, TRTCVideoMirrorType, TRTCVideoStreamType, TRTCAppScene, TRTCAudioRoute, TRTCBeautyStyle, } from './TrtcDefines.js'; |
| | | import TrtcError, { TXLiteJSError, generateError_ } from './TrtcCode.js'; |
| | | const TrtcNativeTrtcCloudModule = uni.requireNativePlugin('TRTCCloudUniPlugin-TRTCCloudImpl'); |
| | | const TXAudioEffectManagerModule = uni.requireNativePlugin('TRTCCloudUniPlugin-TRTCCloudImpl-TXAudioEffectManagerModule'); |
| | | const TrtcEvent = uni.requireNativePlugin('globalEvent'); |
| | | let trtcCloud = null; // trtcCloud 单例 |
| | | export default class TrtcCloudImpl { |
| | | constructor() { |
| | | this.listenersMap_ = new Map(); |
| | | } |
| | | static _createInstance() { |
| | | try { |
| | | if (trtcCloud) { |
| | | return trtcCloud; |
| | | } |
| | | TrtcNativeTrtcCloudModule.sharedInstance(); |
| | | trtcCloud = new TrtcCloudImpl(); |
| | | return trtcCloud; |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | static _getInstance() { |
| | | if (trtcCloud) { |
| | | return trtcCloud; |
| | | } |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_OPERATION, |
| | | message: 'get trtcCloud failed, please create trtcCloud first', |
| | | }); |
| | | } |
| | | static _destroyInstance() { |
| | | try { |
| | | trtcCloud = null; |
| | | TrtcNativeTrtcCloudModule.destroySharedInstance(); |
| | | } |
| | | catch (error) { |
| | | throw new TrtcError({ |
| | | code: error.code || TXLiteJSError.UNKNOWN, |
| | | message: error.message, |
| | | name: error.name, |
| | | }); |
| | | } |
| | | } |
| | | // 截图保存 |
| | | // async saveImage_(base64Data) { |
| | | // return new Promise((resolve, reject) => { |
| | | // let bitmap = new plus.nativeObj.Bitmap(); |
| | | // bitmap.loadBase64Data(base64Data, () => { |
| | | // const url = "_doc/" + new Date().getTime() + ".png"; // url为时间戳命名方式 |
| | | // console.log('saveHeadImgFile', url); |
| | | // bitmap.save(url, { overwrite: true }, (i) => { |
| | | // uni.saveImageToPhotosAlbum({ |
| | | // filePath: url, |
| | | // success: function() { |
| | | // uni.showToast({ |
| | | // title: '图片保存成功', |
| | | // icon: 'none' |
| | | // }) |
| | | // bitmap.clear(); |
| | | // resolve({ code: 0, message: '图片保存成功' }); |
| | | // } |
| | | // }); |
| | | // }, (e) => { |
| | | // uni.showToast({ |
| | | // title: '图片保存失败, 请重新截图', |
| | | // icon: 'none' |
| | | // }) |
| | | // bitmap.clear(); |
| | | // resolve({ code: -1, message: '图片保存失败, 请重新截图' }); |
| | | // }); |
| | | // }); |
| | | // }); |
| | | // } |
| | | on(event, callback) { |
| | | if (typeof event !== NAME.STRING || typeof callback !== NAME.FUNCTION) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the on method parameter types. event type is a ${typeof event}; callback type is a ${typeof callback}`, |
| | | }); |
| | | } |
| | | const nativeListener = (res) => __awaiter(this, void 0, void 0, function* () { |
| | | const { data = [] } = res; |
| | | const code = data[0]; |
| | | const message = data[1]; |
| | | const extraInfo = data[2]; |
| | | switch (event) { |
| | | case 'onEnterRoom': { |
| | | const result = code; |
| | | callback(result); |
| | | break; |
| | | } |
| | | case 'onExitRoom': { |
| | | const reason = code; |
| | | callback(reason); |
| | | break; |
| | | } |
| | | case 'onFirstVideoFrame': { |
| | | const userId = code; |
| | | const streamType = data[1]; |
| | | const width = data[2]; |
| | | const height = data[3]; |
| | | callback({ userId, streamType, width, height }); |
| | | break; |
| | | } |
| | | case 'onFirstAudioFrame': { |
| | | const userId = code; |
| | | callback(userId); |
| | | break; |
| | | } |
| | | case 'onMicDidReady': { |
| | | callback(); |
| | | break; |
| | | } |
| | | case 'onCameraDidReady': { |
| | | callback(); |
| | | break; |
| | | } |
| | | case 'onNetworkQuality': { |
| | | const localQuality = data[0]; |
| | | const remoteQuality = data[1]; |
| | | callback({ localQuality, remoteQuality }); |
| | | break; |
| | | } |
| | | case 'onRemoteUserEnterRoom': { |
| | | const userId = code; |
| | | callback(userId); |
| | | break; |
| | | } |
| | | case 'onRemoteUserLeaveRoom': { |
| | | const userId = code; |
| | | const reason = message; |
| | | callback({ userId, reason }); |
| | | break; |
| | | } |
| | | case 'onSendFirstLocalAudioFrame': { |
| | | callback(); |
| | | break; |
| | | } |
| | | case 'onSendFirstLocalVideoFrame': { |
| | | const streamType = code; |
| | | callback(streamType); |
| | | break; |
| | | } |
| | | case 'onStatistics': { |
| | | const statics = data[0]; |
| | | callback(statics); |
| | | break; |
| | | } |
| | | case 'onUserAudioAvailable': { |
| | | const userId = code; |
| | | const available = message; |
| | | callback({ userId, available }); |
| | | break; |
| | | } |
| | | case 'onUserVideoAvailable': { |
| | | const userId = code; |
| | | const available = message; |
| | | callback({ userId, available }); |
| | | break; |
| | | } |
| | | case 'onUserVoiceVolume': { |
| | | const userVolumes = data[0]; |
| | | const totalVolume = data[1]; |
| | | callback({ userVolumes, totalVolume }); |
| | | break; |
| | | } |
| | | case 'onSwitchRole': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onScreenCaptureStarted': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onScreenCapturePaused': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onScreenCaptureResumed': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onScreenCaptureStopped': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onUserSubStreamAvailable': { |
| | | const userId = code; |
| | | const available = message; |
| | | callback({ userId, available }); |
| | | break; |
| | | } |
| | | case 'onSnapshotComplete': { |
| | | // base64 直接保存到本地图库 |
| | | // const { code: snapShotCode, message: msg } = await this.saveImage_(code); |
| | | // callback({ snapShotCode, message: msg }); |
| | | callback({ base64Data: code, message }); |
| | | break; |
| | | } |
| | | case 'onUserVideoSizeChanged': { |
| | | callback(data); |
| | | break; |
| | | } |
| | | case 'onStart': { |
| | | callback({ id: code, errCode: message }); |
| | | break; |
| | | } |
| | | case 'onPlayProgress': { |
| | | callback({ id: code, curPtsMS: message, durationMS: extraInfo }); |
| | | break; |
| | | } |
| | | case 'onComplete': { |
| | | callback({ id: code, errCode: message }); |
| | | break; |
| | | } |
| | | case 'onConnectOtherRoom': { |
| | | // 拿不到 userid, 为了和 native 参数保持一致,所以空字符串代替 |
| | | callback({ userId: '', errCode: code, errMsg: message }); |
| | | break; |
| | | } |
| | | case 'onDisconnectOtherRoom': { |
| | | callback({ errCode: code, errMsg: message }); |
| | | break; |
| | | } |
| | | case 'onError': { |
| | | console.error(`onError: ${code}, ${message}, ${extraInfo}`); |
| | | callback(generateError_({ message }, code, extraInfo)); |
| | | break; |
| | | } |
| | | case 'onRecvCustomCmdMsg': { |
| | | const userId = code; |
| | | const cmdID = data[1] || 0; |
| | | const seq = data[2] || 0; |
| | | const message = data[3] || ""; |
| | | console.error(`onRecvCustomCmdMsg: ${userId}, ${cmdID}, ${seq}, ${message}`); |
| | | callback({ userId, cmdID, seq, message }); |
| | | break; |
| | | } |
| | | default: { |
| | | callback({ code, message, extraInfo }); |
| | | } |
| | | } |
| | | }); |
| | | this.listenersMap_.set(event, nativeListener); // 多次设置同一个事件时,后面的 callback 覆盖前面 |
| | | TrtcEvent.addEventListener(event, nativeListener); |
| | | } |
| | | off(event) { |
| | | if (typeof event !== NAME.STRING) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the off method parameter types. event type is a ${typeof event} not a ${NAME.STRING}`, |
| | | }); |
| | | } |
| | | try { |
| | | if (event === '*') { |
| | | this.listenersMap_.forEach((value, key) => { |
| | | TrtcEvent.removeEventListener(key, value); |
| | | }); |
| | | this.listenersMap_.clear(); |
| | | } |
| | | else { |
| | | TrtcEvent.removeEventListener(event, this.listenersMap_.get(event)); |
| | | this.listenersMap_.delete(event); |
| | | } |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | enterRoom(params, scene) { |
| | | if (scene !== TRTCAppScene.TRTCAppSceneVideoCall && scene !== TRTCAppScene.TRTCAppSceneLIVE && scene !== TRTCAppScene.TRTCAppSceneAudioCall && scene !== TRTCAppScene.TRTCAppSceneVoiceChatRoom) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the enterRoom method parameters. scene is not of TRTCAppScene`, |
| | | }); |
| | | } |
| | | try { |
| | | const enterRoomParams = Object.assign(Object.assign({}, params), { role: params.role || TRTCRoleType.TRTCRoleAnchor, appScene: scene }); |
| | | TrtcNativeTrtcCloudModule.enterRoom(enterRoomParams); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | exitRoom() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.exitRoom(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | connectOtherRoom(params) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.connectOtherRoom(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | disconnectOtherRoom() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.disconnectOtherRoom(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | switchRole(role) { |
| | | if (role !== TRTCRoleType.TRTCRoleAnchor && role !== TRTCRoleType.TRTCRoleAudience) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the switchRole method parameter. role is not of TRTCRoleType`, |
| | | }); |
| | | } |
| | | try { |
| | | role && TrtcNativeTrtcCloudModule.switchRole(role); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | startLocalPreview(isFrontCamera = true, viewId) { |
| | | if (typeof isFrontCamera !== NAME.BOOLEAN || !viewId || typeof viewId !== NAME.STRING) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the startLocalPreview method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | let param = { isFrontCamera: !!isFrontCamera }; |
| | | param = viewId ? Object.assign(Object.assign({}, param), { userId: viewId }) : param; |
| | | TrtcNativeTrtcCloudModule.startLocalPreview(param); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setVideoEncoderParam(param) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setVideoEncoderParam(param); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopLocalPreview() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.stopLocalPreview(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | switchCamera(isFrontCamera) { |
| | | if (typeof isFrontCamera !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the switchCamera method parameter`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.switchCamera(isFrontCamera); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setLocalRenderParams(params) { |
| | | try { |
| | | const { rotation = TRTCVideoRotation.TRTCVideoRotation_0, fillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fill, mirrorType = TRTCVideoMirrorType.TRTCVideoMirrorType_Auto } = params; |
| | | TrtcNativeTrtcCloudModule.setLocalRenderParams({ |
| | | rotation, |
| | | fillMode, |
| | | mirrorType, |
| | | }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | muteLocalVideo(streamType, mute) { |
| | | if (streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub || typeof mute !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the muteLocalVideo method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.muteLocalVideo({ streamType, mute: !!mute }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | startRemoteView(userId, streamType, viewId) { |
| | | if (!userId || streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSmall && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub || !viewId) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the startRemoteView method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.startRemoteView({ userId, streamType, viewId }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopRemoteView(userId, streamType) { |
| | | if (!userId || streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSmall && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the stopRemoteView method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.stopRemoteView({ userId, streamType }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 远端渲染设置 |
| | | setRemoteRenderParams(userId, streamType, params) { |
| | | try { |
| | | if (!userId || (streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub)) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the snapshotVideo method parameters`, |
| | | }); |
| | | } |
| | | const { rotation = TRTCVideoRotation.TRTCVideoRotation_0, fillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fill, mirrorType = TRTCVideoMirrorType.TRTCVideoMirrorType_Auto } = params; |
| | | TrtcNativeTrtcCloudModule.setRemoteRenderParams({ |
| | | userId, |
| | | streamType, |
| | | rotation, |
| | | fillMode, |
| | | mirrorType |
| | | }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 设置视频编码器输出的画面方向 |
| | | setVideoEncoderRotation(rotation) { |
| | | if (typeof rotation !== NAME.NUMBER) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setVideoEncoderRotation method parameter`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setVideoEncoderRotation(rotation); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 设置编码器输出的画面镜像模式 |
| | | setVideoEncoderMirror(mirror) { |
| | | if (typeof mirror !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setVideoEncoderMirror method parameter`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setVideoEncoderMirror(mirror); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 设置重力感应的适配模式 |
| | | setGSensorMode(mode) { |
| | | if (typeof mode !== NAME.NUMBER) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setGSensorMode method parameter`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setGSensorMode(mode); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 截图 |
| | | snapshotVideo(userId, streamType, sourceType) { |
| | | if (streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the snapshotVideo method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.snapshotVideo({ userId: userId || null, streamType, sourceType }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | startLocalAudio(quality = TRTCAudioQuality.TRTCAudioQualityDefault) { |
| | | if (quality !== TRTCAudioQuality.TRTCAudioQualitySpeech && quality !== TRTCAudioQuality.TRTCAudioQualityDefault && quality !== TRTCAudioQuality.TRTCAudioQualityMusic) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the startLocalAudio method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.startLocalAudio(quality); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopLocalAudio() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.stopLocalAudio(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | muteLocalAudio(mute) { |
| | | if (typeof mute !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the muteLocalAudio method parameters, mute type is a ${typeof mute} not a ${NAME.BOOLEAN}`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.muteLocalAudio(!!mute); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | muteRemoteAudio(userId, mute) { |
| | | if (typeof mute !== NAME.BOOLEAN || !userId) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the muteRemoteAudio method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.muteRemoteAudio({ userId, mute: !!mute }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | muteAllRemoteAudio(mute) { |
| | | if (typeof mute !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the muteAllRemoteAudio method parameters, mute type is a ${typeof mute} not a ${NAME.BOOLEAN}`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.muteAllRemoteAudio(!!mute); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setAudioRoute(route) { |
| | | if (route !== TRTCAudioRoute.TRTCAudioRouteSpeaker && route !== TRTCAudioRoute.TRTCAudioRouteEarpiece) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setAudioRoute method parameter, route is not of TRTCAudioRoute`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setAudioRoute(route); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | enableAudioVolumeEvaluation(interval) { |
| | | if (typeof interval !== NAME.NUMBER) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the enableAudioVolumeEvaluation method parameter, interval type is a ${typeof interval} not a ${NAME.NUMBER}`, |
| | | }); |
| | | } |
| | | try { |
| | | interval > 0 && TrtcNativeTrtcCloudModule.enableAudioVolumeEvaluation(interval); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 美颜 + 水印 |
| | | // |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | setBeautyStyle(beautyStyle) { |
| | | if (beautyStyle !== TRTCBeautyStyle.TRTCBeautyStyleSmooth && beautyStyle !== TRTCBeautyStyle.TRTCBeautyStyleNature && beautyStyle !== TRTCBeautyStyle.TRTCBeautyStylePitu) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setBeautyStyle method parameter, beautyStyle is not of TRTCBeautyStyle`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setBeautyStyle(beautyStyle); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setBeautyLevel(beautyLevel) { |
| | | if (typeof beautyLevel !== NAME.NUMBER || (beautyLevel < 0 || beautyLevel > 9)) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setBeautyLevel method parameter, beautyLevel should in the range 0-9`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setBeautyLevel(beautyLevel); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 背景音效 |
| | | // |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | startPlayMusic(musicParam) { |
| | | try { |
| | | const { id = 0 } = musicParam || {}; |
| | | TXAudioEffectManagerModule.startPlayMusic(Object.assign(Object.assign({}, musicParam), { ID: id })); // v1.2.0 的 iOS 解析的是 ID, v1.2.1 插件进行了修复 |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopPlayMusic(id) { |
| | | try { |
| | | TXAudioEffectManagerModule.stopPlayMusic(id); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | pausePlayMusic(id) { |
| | | try { |
| | | TXAudioEffectManagerModule.pausePlayMusic(id); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | resumePlayMusic(id) { |
| | | try { |
| | | TXAudioEffectManagerModule.resumePlayMusic(id); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 屏幕分享 |
| | | // |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | setSubStreamEncoderParam(param) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setSubStreamEncoderParam(param); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | startScreenCapture(streamType = TRTCVideoStreamType.TRTCVideoStreamTypeSub, encParams = {}, shareParams = {}) { |
| | | try { |
| | | let platform = uni.getSystemInfoSync().platform; |
| | | if ((streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig)) { |
| | | streamType = TRTCVideoStreamType.TRTCVideoStreamTypeSub; |
| | | } |
| | | const { enableForegroundService = true, appGroup } = shareParams; // 默认开启前台服务, 避免退后台后进程被杀 |
| | | const screenCaptureParams = Object.assign({ streamType }, encParams); |
| | | if (platform === NAME.ANDROID) { |
| | | TrtcNativeTrtcCloudModule.startScreenCapture(Object.assign(Object.assign({}, screenCaptureParams), { enableForegroundService })); |
| | | } |
| | | if (platform === NAME.IOS) { |
| | | if (typeof appGroup === 'string' && appGroup.length) { |
| | | // 开始全系统的屏幕分享(仅支持 iOS 11.0 及以上系统) |
| | | const params = { streamType, encParams, appGroup }; |
| | | TrtcNativeTrtcCloudModule.startScreenCaptureByReplaykit(params); |
| | | } |
| | | else { |
| | | // 开始应用内的屏幕分享(仅支持 iOS 13.0 及以上系统) |
| | | TrtcNativeTrtcCloudModule.startScreenCaptureInApp(screenCaptureParams); |
| | | } |
| | | } |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopScreenCapture() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.stopScreenCapture(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | pauseScreenCapture() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.pauseScreenCapture(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | resumeScreenCapture() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.resumeScreenCapture(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | callExperimentalAPI(params) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.callExperimentalAPI(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setSystemVolumeType(type) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setSystemVolumeType(type); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setVideoMuteImage(fps, image) { |
| | | const params = { |
| | | fps, |
| | | filePath: image, |
| | | }; |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setVideoMuteImage(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | enableEncSmallVideoStream(enable, smallVideoEncParam) { |
| | | const params = Object.assign({ enable }, smallVideoEncParam); |
| | | try { |
| | | TrtcNativeTrtcCloudModule.enableEncSmallVideoStream(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | sendCustomCmdMsg(params) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.sendCustomCmdMsg(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | import { NAME, errorCodeUrl } from './constants.js'; |
| | | /** |
| | | * @namespace ErrorCode |
| | | * |
| | | * @description 错误码、警告码和事件列表 |
| | | */ |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // (一)错误码(严重) |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * @memberof ErrorCode |
| | | * @typedef 错误码(严重) |
| | | * @description SDK 错误码(严重)对照表 |
| | | * | 符号 | 值 | 含义 | |
| | | * |---|---|---| |
| | | * |ERR_NULL|0|无错误| |
| | | * |ERR_ROOM_ENTER_FAIL|-3301|进入房间失败| |
| | | * |ERR_ENTER_ROOM_PARAM_NULL|-3316|进房参数为空,请检查 enterRoom:appScene: 接口调用是否传入有效的 param| |
| | | * |ERR_SDK_APPID_INVALID|-3317|进房参数 sdkAppId 错误| |
| | | * |ERR_ROOM_ID_INVALID|-3318|进房参数 roomId 错误| |
| | | * |ERR_USER_ID_INVALID|-3319|进房参数 userID 不正确| |
| | | * |ERR_USER_SIG_INVALID|-3320|进房参数 userSig 不正确| |
| | | * |ERR_ROOM_REQUEST_ENTER_ROOM_TIMEOUT|-3308|请求进房超时,请检查网络| |
| | | * |ERR_SERVER_INFO_SERVICE_SUSPENDED|-100013|服务不可用。请检查:套餐包剩余分钟数是否大于0,腾讯云账号是否欠费| |
| | | * |ERR_ROOM_REQUEST_QUIT_ROOM_TIMEOUT|-3325|请求退房超时| |
| | | * |ERR_CAMERA_START_FAIL|-1301|打开摄像头失败,例如在 Windows 或 Mac 设备,摄像头的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序| |
| | | * |ERR_CAMERA_NOT_AUTHORIZED|-1314|摄像头设备未授权,通常在移动设备出现,可能是权限被用户拒绝了| |
| | | * |ERR_CAMERA_SET_PARAM_FAIL|-1315|摄像头参数设置出错(参数不支持或其它)| |
| | | * |ERR_CAMERA_OCCUPY|-1316|摄像头正在被占用中,可尝试打开其他摄像头| |
| | | * |ERR_MIC_START_FAIL|-1302|打开麦克风失败,例如在 Windows 或 Mac 设备,麦克风的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序| |
| | | * |ERR_MIC_NOT_AUTHORIZED|-1317|麦克风设备未授权,通常在移动设备出现,可能是权限被用户拒绝了| |
| | | * |ERR_MIC_SET_PARAM_FAIL|-1318|麦克风设置参数失败| |
| | | * |ERR_MIC_OCCUPY|-1319|麦克风正在被占用中,例如移动设备正在通话时,打开麦克风会失败| |
| | | * |ERR_MIC_STOP_FAIL|-1320|停止麦克风失败| |
| | | * |ERR_SPEAKER_START_FAIL|-1321|打开扬声器失败,例如在 Windows 或 Mac 设备,扬声器的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序| |
| | | * |ERR_SPEAKER_SET_PARAM_FAIL|-1322|扬声器设置参数失败| |
| | | * |ERR_SPEAKER_STOP_FAIL|-1323|停止扬声器失败| |
| | | * |ERR_SCREEN_CAPTURE_START_FAIL|-1308|开始录屏失败,如果在移动设备出现,可能是权限被用户拒绝了,如果在 Windows 或 Mac 系统的设备出现,请检查录屏接口的参数是否符合要求| |
| | | * |ERR_SCREEN_CAPTURE_UNSURPORT|-1309|录屏失败,在 Android 平台,需要5.0以上的系统| |
| | | * |ERR_SERVER_CENTER_NO_PRIVILEDGE_PUSH_SUB_VIDEO|-102015|没有权限上行辅路| |
| | | * |ERR_SERVER_CENTER_ANOTHER_USER_PUSH_SUB_VIDEO|-102016|其他用户正在上行辅路| |
| | | * |ERR_VIDEO_ENCODE_FAIL|-1303|视频帧编码失败,例如 iOS 设备切换到其他应用时,硬编码器可能被系统释放,再切换回来时,硬编码器重启前,可能会抛出| |
| | | * |ERR_UNSUPPORTED_RESOLUTION|-1305|不支持的视频分辨率| |
| | | * |ERR_AUDIO_ENCODE_FAIL|-1304|音频帧编码失败,例如传入自定义音频数据,SDK 无法处理| |
| | | * |ERR_UNSUPPORTED_SAMPLERATE|-1306|不支持的音频采样率| |
| | | * |ERR_PIXEL_FORMAT_UNSUPPORTED|-1327|设置的 pixel format 不支持| |
| | | * |ERR_BUFFER_TYPE_UNSUPPORTED|-1328|设置的 buffer type 不支持| |
| | | * |ERR_PUBLISH_CDN_STREAM_REQUEST_TIME_OUT|-3321|旁路转推请求超时| |
| | | * |ERR_CLOUD_MIX_TRANSCODING_REQUEST_TIME_OUT|-3322|云端混流请求超时| |
| | | * |ERR_PUBLISH_CDN_STREAM_SERVER_FAILED|-3323|旁路转推回包异常| |
| | | * |ERR_CLOUD_MIX_TRANSCODING_SERVER_FAILED|-3324|云端混流回包异常| |
| | | * |ERR_ROOM_REQUEST_START_PUBLISHING_TIMEOUT|-3333|开始向腾讯云的直播 CDN 推流信令超时| |
| | | * |ERR_ROOM_REQUEST_START_PUBLISHING_ERROR|-3334|开始向腾讯云的直播 CDN 推流信令异常| |
| | | * |ERR_ROOM_REQUEST_STOP_PUBLISHING_TIMEOUT|-3335|停止向腾讯云的直播 CDN 推流信令超时| |
| | | * |ERR_ROOM_REQUEST_STOP_PUBLISHING_ERROR|-3336|停止向腾讯云的直播 CDN 推流信令异常| |
| | | * |ERR_ROOM_REQUEST_CONN_ROOM_TIMEOUT|-3326|请求连麦超时| |
| | | * |ERR_ROOM_REQUEST_DISCONN_ROOM_TIMEOUT|-3327|请求退出连麦超时| |
| | | * |ERR_ROOM_REQUEST_CONN_ROOM_INVALID_PARAM|-3328|无效参数| |
| | | * |ERR_CONNECT_OTHER_ROOM_AS_AUDIENCE|-3330|当前是观众角色,不能请求或断开跨房连麦,需要先 switchRole() 到主播| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_NOT_SUPPORT|-102031|不支持跨房间连麦| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_REACH_MAX_NUM|-102032|达到跨房间连麦上限| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_REACH_MAX_RETRY_TIMES|-102033|跨房间连麦重试次数耗尽| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_REQ_TIMEOUT|-102034|跨房间连麦请求超时| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_REQ|-102035|跨房间连麦请求格式错误| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_NO_SIG|-102036|跨房间连麦无签名| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_DECRYPT_SIG|-102037|跨房间连麦签名解密失败| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_NO_KEY|-102038|未找到跨房间连麦签名解密密钥| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_PARSE_SIG|-102039|跨房间连麦签名解析错误| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_INVALID_SIG_TIME|-102040|跨房间连麦签名时间戳错误| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_SIG_GROUPID|-102041|跨房间连麦签名不匹配| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_NOT_CONNED|-102042|本房间无连麦| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_USER_NOT_CONNED|-102043|本用户未发起连麦| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_FAILED|-102044|跨房间连麦失败| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CANCEL_FAILED|-102045|取消跨房间连麦失败| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_ROOM_NOT_EXIST|-102046|被连麦房间不存在| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_REACH_MAX_ROOM|-102047|被连麦房间达到连麦上限| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_NOT_EXIST|-102048|被连麦用户不存在| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_DELETED|-102049|被连麦用户已被删除| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_FULL|-102050|被连麦用户达到资源上限| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_INVALID_SEQ|-102051|连麦请求序号错乱| |
| | | */ |
| | | export const TXLiteAVError = { |
| | | /** 无错误 */ |
| | | ERR_NULL: 0, |
| | | /** 进入房间失败 */ |
| | | ERR_ROOM_ENTER_FAIL: -3301, |
| | | /** 进房参数为空,请检查 enterRoom:appScene: 接口调用是否传入有效的 param */ |
| | | ERR_ENTER_ROOM_PARAM_NULL: -3316, |
| | | /** 进房参数 sdkAppId 错误 */ |
| | | ERR_SDK_APPID_INVALID: -3317, |
| | | /** 进房参数 roomId 错误 */ |
| | | ERR_ROOM_ID_INVALID: -3318, |
| | | /** 进房参数 userID 不正确 */ |
| | | ERR_USER_ID_INVALID: -3319, |
| | | /** 进房参数 userSig 不正确 */ |
| | | ERR_USER_SIG_INVALID: -3320, |
| | | /** 请求进房超时,请检查网络 */ |
| | | ERR_ROOM_REQUEST_ENTER_ROOM_TIMEOUT: -3308, |
| | | /** 服务不可用。请检查:套餐包剩余分钟数是否大于0,腾讯云账号是否欠费 */ |
| | | ERR_SERVER_INFO_SERVICE_SUSPENDED: -100013, |
| | | /** 请求退房超时 */ |
| | | ERR_ROOM_REQUEST_QUIT_ROOM_TIMEOUT: -3325, |
| | | /** 打开摄像头失败,例如在 Windows 或 Mac 设备,摄像头的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序 */ |
| | | ERR_CAMERA_START_FAIL: -1301, |
| | | /** 摄像头设备未授权,通常在移动设备出现,可能是权限被用户拒绝了 */ |
| | | ERR_CAMERA_NOT_AUTHORIZED: -1314, |
| | | /** 摄像头参数设置出错(参数不支持或其它) */ |
| | | ERR_CAMERA_SET_PARAM_FAIL: -1315, |
| | | /** 摄像头正在被占用中,可尝试打开其他摄像头 */ |
| | | ERR_CAMERA_OCCUPY: -1316, |
| | | /** 打开麦克风失败,例如在 Windows 或 Mac 设备,麦克风的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序 */ |
| | | ERR_MIC_START_FAIL: -1302, |
| | | /** 麦克风设备未授权,通常在移动设备出现,可能是权限被用户拒绝了 */ |
| | | ERR_MIC_NOT_AUTHORIZED: -1317, |
| | | /** 麦克风设置参数失败 */ |
| | | ERR_MIC_SET_PARAM_FAIL: -1318, |
| | | /** 麦克风正在被占用中,例如移动设备正在通话时,打开麦克风会失败 */ |
| | | ERR_MIC_OCCUPY: -1319, |
| | | /** 停止麦克风失败 */ |
| | | ERR_MIC_STOP_FAIL: -1320, |
| | | /** 打开扬声器失败,例如在 Windows 或 Mac 设备,扬声器的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序 */ |
| | | ERR_SPEAKER_START_FAIL: -1321, |
| | | /** 扬声器设置参数失败 */ |
| | | ERR_SPEAKER_SET_PARAM_FAIL: -1322, |
| | | /** 停止扬声器失败 */ |
| | | ERR_SPEAKER_STOP_FAIL: -1323, |
| | | /** 开始录屏失败,如果在移动设备出现,可能是权限被用户拒绝了,如果在 Windows 或 Mac 系统的设备出现,请检查录屏接口的参数是否符合要求 */ |
| | | ERR_SCREEN_CAPTURE_START_FAIL: -1308, |
| | | /** 录屏失败,在 Android 平台,需要5.0以上的系统 */ |
| | | ERR_SCREEN_CAPTURE_UNSURPORT: -1309, |
| | | /** 没有权限上行辅路 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_PUSH_SUB_VIDEO: -102015, |
| | | /** 其他用户正在上行辅路 */ |
| | | ERR_SERVER_CENTER_ANOTHER_USER_PUSH_SUB_VIDEO: -102016, |
| | | /** 视频帧编码失败,例如 iOS 设备切换到其他应用时,硬编码器可能被系统释放,再切换回来时,硬编码器重启前,可能会抛出 */ |
| | | ERR_VIDEO_ENCODE_FAIL: -1303, |
| | | /** 音频帧编码失败,例如传入自定义音频数据,SDK 无法处理 */ |
| | | ERR_AUDIO_ENCODE_FAIL: -1304, |
| | | /** 不支持的视频分辨率 */ |
| | | ERR_UNSUPPORTED_RESOLUTION: -1305, |
| | | /** 不支持的音频采样率 */ |
| | | ERR_UNSUPPORTED_SAMPLERATE: -1306, |
| | | /** 设置的 pixel format 不支持 */ |
| | | ERR_PIXEL_FORMAT_UNSUPPORTED: -1327, |
| | | /** 设置的 buffer type 不支持 */ |
| | | ERR_BUFFER_TYPE_UNSUPPORTED: -1328, |
| | | /** 旁路转推请求超时 */ |
| | | ERR_PUBLISH_CDN_STREAM_REQUEST_TIME_OUT: -3321, |
| | | /** 云端混流请求超时 */ |
| | | ERR_CLOUD_MIX_TRANSCODING_REQUEST_TIME_OUT: -3322, |
| | | /** 旁路转推回包异常 */ |
| | | ERR_PUBLISH_CDN_STREAM_SERVER_FAILED: -3323, |
| | | /** 云端混流回包异常 */ |
| | | ERR_CLOUD_MIX_TRANSCODING_SERVER_FAILED: -3324, |
| | | /** 开始向腾讯云的直播 CDN 推流信令超时 */ |
| | | ERR_ROOM_REQUEST_START_PUBLISHING_TIMEOUT: -3333, |
| | | /** 开始向腾讯云的直播 CDN 推流信令异常 */ |
| | | ERR_ROOM_REQUEST_START_PUBLISHING_ERROR: -3334, |
| | | /** 停止向腾讯云的直播 CDN 推流信令超时 */ |
| | | ERR_ROOM_REQUEST_STOP_PUBLISHING_TIMEOUT: -3335, |
| | | /** 停止向腾讯云的直播 CDN 推流信令异常 */ |
| | | ERR_ROOM_REQUEST_STOP_PUBLISHING_ERROR: -3336, |
| | | /** 请求连麦超时 */ |
| | | ERR_ROOM_REQUEST_CONN_ROOM_TIMEOUT: -3326, |
| | | /** 请求退出连麦超时 */ |
| | | ERR_ROOM_REQUEST_DISCONN_ROOM_TIMEOUT: -3327, |
| | | /** 无效参数 */ |
| | | ERR_ROOM_REQUEST_CONN_ROOM_INVALID_PARAM: -3328, |
| | | /** 当前是观众角色,不能请求或断开跨房连麦,需要先 switchRole() 到主播 */ |
| | | ERR_CONNECT_OTHER_ROOM_AS_AUDIENCE: -3330, |
| | | /** 不支持跨房间连麦 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_NOT_SUPPORT: -102031, |
| | | /** 达到跨房间连麦上限 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_REACH_MAX_NUM: -102032, |
| | | /** 跨房间连麦重试次数耗尽 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_REACH_MAX_RETRY_TIMES: -102033, |
| | | /** 跨房间连麦请求超时 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_REQ_TIMEOUT: -102034, |
| | | /** 跨房间连麦请求格式错误 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_REQ: -102035, |
| | | /** 跨房间连麦无签名 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_NO_SIG: -102036, |
| | | /** 跨房间连麦签名解密失败 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_DECRYPT_SIG: -102037, |
| | | /** 未找到跨房间连麦签名解密密钥 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_NO_KEY: -102038, |
| | | /** 跨房间连麦签名解析错误 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_PARSE_SIG: -102039, |
| | | /** 跨房间连麦签名时间戳错误 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_INVALID_SIG_TIME: -102040, |
| | | /** 跨房间连麦签名不匹配 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_SIG_GROUPID: -102041, |
| | | /** 本房间无连麦 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_NOT_CONNED: -102042, |
| | | /** 本用户未发起连麦 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_USER_NOT_CONNED: -102043, |
| | | /** 跨房间连麦失败 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_FAILED: -102044, |
| | | /** 取消跨房间连麦失败 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CANCEL_FAILED: -102045, |
| | | /** 被连麦房间不存在 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_ROOM_NOT_EXIST: -102046, |
| | | /** 被连麦房间达到连麦上限 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_REACH_MAX_ROOM: -102047, |
| | | /** 被连麦用户不存在 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_NOT_EXIST: -102048, |
| | | /** 被连麦用户已被删除 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_DELETED: -102049, |
| | | /** 被连麦用户达到资源上限 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_FULL: -102050, |
| | | /** 连麦请求序号错乱 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_INVALID_SEQ: -102051, |
| | | /** 直播,推流出现网络断开,且经过多次重试无法恢复 */ |
| | | ERR_RTMP_PUSH_NET_DISCONNECT: -1307, |
| | | /** 直播,推流地址非法,例如不是 RTMP 协议的地址 */ |
| | | ERR_RTMP_PUSH_INVALID_ADDRESS: -1313, |
| | | /** 直播,连接推流服务器失败(若支持智能选路,IP 全部失败) */ |
| | | ERR_RTMP_PUSH_NET_ALLADDRESS_FAIL: -1324, |
| | | /** 直播,网络不可用,请确认 WiFi、移动数据或者有线网络是否正常 */ |
| | | ERR_RTMP_PUSH_NO_NETWORK: -1325, |
| | | /** 直播,服务器拒绝连接请求,可能是该推流地址已经被占用,或者 TXSecret 校验失败,或者是过期了,或者是欠费了 */ |
| | | ERR_RTMP_PUSH_SERVER_REFUSE: -1326, |
| | | /** 直播,网络断连,且经多次重连抢救无效,可以放弃治疗,更多重试请自行重启播放 */ |
| | | ERR_PLAY_LIVE_STREAM_NET_DISCONNECT: -2301, |
| | | /** 直播,获取加速拉流的地址失败 */ |
| | | ERR_GET_RTMP_ACC_URL_FAIL: -2302, |
| | | /** 播放的文件不存在 */ |
| | | ERR_FILE_NOT_FOUND: -2303, |
| | | /** H265 解码失败 */ |
| | | ERR_HEVC_DECODE_FAIL: -2304, |
| | | /** 点播,音视频流解密失败 */ |
| | | ERR_VOD_DECRYPT_FAIL: -2305, |
| | | /** 点播,获取点播文件信息失败 */ |
| | | ERR_GET_VODFILE_MEDIAINFO_FAIL: -2306, |
| | | /** 直播,切流失败(切流可以播放不同画面大小的视频) */ |
| | | ERR_PLAY_LIVE_STREAM_SWITCH_FAIL: -2307, |
| | | /** 直播,服务器拒绝连接请求 */ |
| | | ERR_PLAY_LIVE_STREAM_SERVER_REFUSE: -2308, |
| | | /** 直播,RTMPACC 低延时拉流失败,且经过多次重试无法恢复 */ |
| | | ERR_RTMP_ACC_FETCH_STREAM_FAIL: -2309, |
| | | /** 心跳失败,客户端定时向服务器发送数据包,告诉服务器自己活着,这个错误通常是发包超时 */ |
| | | ERR_ROOM_HEARTBEAT_FAIL: -3302, |
| | | /** 拉取接口机服务器地址失败 */ |
| | | ERR_ROOM_REQUEST_IP_FAIL: -3303, |
| | | /** 连接接口机服务器失败 */ |
| | | ERR_ROOM_CONNECT_FAIL: -3304, |
| | | /** 请求视频位失败 */ |
| | | ERR_ROOM_REQUEST_AVSEAT_FAIL: -3305, |
| | | /** 请求 token https 超时,请检查网络是否正常,或网络防火墙是否放行 https 访问 official.opensso.tencent-cloud.com:443 */ |
| | | ERR_ROOM_REQUEST_TOKEN_HTTPS_TIMEOUT: -3306, |
| | | /** 请求 IP 和 sig 超时,请检查网络是否正常,或网络防火墙是否放行 UDP 访问下列 IP 和域名 query.tencent-cloud.com:8000 162.14.23.140:8000 162.14.7.49:8000 */ |
| | | ERR_ROOM_REQUEST_IP_TIMEOUT: -3307, |
| | | /** 请求视频位超时 */ |
| | | ERR_ROOM_REQUEST_VIDEO_FLAG_TIMEOUT: -3309, |
| | | /** 请求视频数据超时 */ |
| | | ERR_ROOM_REQUEST_VIDEO_DATA_ROOM_TIMEOUT: -3310, |
| | | /** 请求修改视频能力项超时 */ |
| | | ERR_ROOM_REQUEST_CHANGE_ABILITY_TIMEOUT: -3311, |
| | | /** 请求状态上报超时 */ |
| | | ERR_ROOM_REQUEST_STATUS_REPORT_TIMEOUT: -3312, |
| | | /** 请求关闭视频超时 */ |
| | | ERR_ROOM_REQUEST_CLOSE_VIDEO_TIMEOUT: -3313, |
| | | /** 请求接收视频项超时 */ |
| | | ERR_ROOM_REQUEST_SET_RECEIVE_TIMEOUT: -3314, |
| | | /** 请求 token 无效参数,请检查 TRTCParams.userSig 是否填写正确 */ |
| | | ERR_ROOM_REQUEST_TOKEN_INVALID_PARAMETER: -3315, |
| | | /** 请求 AES TOKEN 时,server 返回的内容是空的 */ |
| | | ERR_ROOM_REQUEST_AES_TOKEN_RETURN_ERROR: -3329, |
| | | /** 请求接口机 IP 返回的列表为空的 */ |
| | | ERR_ACCIP_LIST_EMPTY: -3331, |
| | | /** 请求发送 Json 信令超时 */ |
| | | ERR_ROOM_REQUEST_SEND_JSON_CMD_TIMEOUT: -3332, |
| | | // Info 服务器(查询接口机 IP), 服务器错误码,数值范围[-100000, -110000] |
| | | /** server 解包错误,可能请求数据被篡改 */ |
| | | ERR_SERVER_INFO_UNPACKING_ERROR: -100000, |
| | | /** TOKEN 错误 */ |
| | | ERR_SERVER_INFO_TOKEN_ERROR: -100001, |
| | | /** 分配接口机错误 */ |
| | | ERR_SERVER_INFO_ALLOCATE_ACCESS_FAILED: -100002, |
| | | /** 生成签名错误 */ |
| | | ERR_SERVER_INFO_GENERATE_SIGN_FAILED: -100003, |
| | | /** https token 超时 */ |
| | | ERR_SERVER_INFO_TOKEN_TIMEOUT: -100004, |
| | | /** 无效的命令字 */ |
| | | ERR_SERVER_INFO_INVALID_COMMAND: -100005, |
| | | /** 权限位校验失败 */ |
| | | ERR_SERVER_INFO_PRIVILEGE_FLAG_ERROR: -100006, |
| | | /** https 请求时,生成加密 key 错误 */ |
| | | ERR_SERVER_INFO_GENERATE_KEN_ERROR: -100007, |
| | | /** https 请求时,生成 token 错误 */ |
| | | ERR_SERVER_INFO_GENERATE_TOKEN_ERROR: -100008, |
| | | /** 数据库查询失败(房间相关存储信息) */ |
| | | ERR_SERVER_INFO_DATABASE: -100009, |
| | | /** 房间号错误 */ |
| | | ERR_SERVER_INFO_BAD_ROOMID: -100010, |
| | | /** 场景或角色错误 */ |
| | | ERR_SERVER_INFO_BAD_SCENE_OR_ROLE: -100011, |
| | | /** 房间号转换出错 */ |
| | | ERR_SERVER_INFO_ROOMID_EXCHANGE_FAILED: -100012, |
| | | /** 房间号非法 */ |
| | | ERR_SERVER_INFO_STRGROUP_HAS_INVALID_CHARS: -100014, |
| | | /** 非法SDKAppid */ |
| | | ERR_SERVER_INFO_LACK_SDKAPPID: -100015, |
| | | /** 无效请求, 旧版 0x1 要求带 Token; ECDH 要求带 ECDH Publich Key; 两个都没有就按报错 */ |
| | | ERR_SERVER_INFO_INVALID: -100016, |
| | | /** 生成公钥失败 */ |
| | | ERR_SERVER_INFO_ECDH_GET_KEY: -100017, |
| | | /** 获取tinyid失败 */ |
| | | ERR_SERVER_INFO_ECDH_GET_TINYID: -100018, |
| | | // Access 接口机 |
| | | /** token 过期 */ |
| | | ERR_SERVER_ACC_TOKEN_TIMEOUT: -101000, |
| | | /** 签名错误 */ |
| | | ERR_SERVER_ACC_SIGN_ERROR: -101001, |
| | | /** 签名超时 */ |
| | | ERR_SERVER_ACC_SIGN_TIMEOUT: -101002, |
| | | /** 房间不存在 */ |
| | | ERR_SERVER_ACC_ROOM_NOT_EXIST: -101003, |
| | | /** 后台房间标识 roomId 错误 */ |
| | | ERR_SERVER_ACC_ROOMID: -101004, |
| | | /** 后台用户位置标识 locationId 错误 */ |
| | | ERR_SERVER_ACC_LOCATIONID: -101005, |
| | | // center 服务器(信令和流控处理等任务) |
| | | /** 后台错误 */ |
| | | ERR_SERVER_CENTER_SYSTEM_ERROR: -102000, |
| | | /** 无效的房间 Id */ |
| | | ERR_SERVER_CENTER_INVALID_ROOMID: -102001, |
| | | /** 创建房间失败 */ |
| | | ERR_SERVER_CENTER_CREATE_ROOM_FAILED: -102002, |
| | | /** 签名错误 */ |
| | | ERR_SERVER_CENTER_SIGN_ERROR: -102003, |
| | | /** 签名过期 */ |
| | | ERR_SERVER_CENTER_SIGN_TIMEOUT: -102004, |
| | | /** 房间不存在 */ |
| | | ERR_SERVER_CENTER_ROOM_NOT_EXIST: -102005, |
| | | /** 房间添加用户失败 */ |
| | | ERR_SERVER_CENTER_ADD_USER_FAILED: -102006, |
| | | /** 查找用户失败 */ |
| | | ERR_SERVER_CENTER_FIND_USER_FAILED: -102007, |
| | | /** 频繁切换终端 */ |
| | | ERR_SERVER_CENTER_SWITCH_TERMINATION_FREQUENTLY: -102008, |
| | | /** locationid 错误 */ |
| | | ERR_SERVER_CENTER_LOCATION_NOT_EXIST: -102009, |
| | | /** 没有权限创建房间 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_CREATE_ROOM: -102010, |
| | | /** 没有权限进入房间 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_ENTER_ROOM: -102011, |
| | | /** 辅路抢视频位、申请辅路请求类型参数错误 */ |
| | | ERR_SERVER_CENTER_INVALID_PARAMETER_SUB_VIDEO: -102012, |
| | | /** 没有权限上视频 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_PUSH_VIDEO: -102013, |
| | | /** 没有空闲路由表 */ |
| | | ERR_SERVER_CENTER_ROUTE_TABLE_ERROR: -102014, |
| | | /** 当前用户没有上行辅路 */ |
| | | ERR_SERVER_CENTER_NOT_PUSH_SUB_VIDEO: -102017, |
| | | /** 用户被删除状态 */ |
| | | ERR_SERVER_CENTER_USER_WAS_DELETED: -102018, |
| | | /** 没有权限请求视频 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_REQUEST_VIDEO: -102019, |
| | | /** 进房参数 bussInfo 错误 */ |
| | | ERR_SERVER_CENTER_INVALID_PARAMETER: -102023, |
| | | /** 请求 I 帧未知 opType */ |
| | | ERR_SERVER_CENTER_I_FRAME_UNKNOW_TYPE: -102024, |
| | | /** 请求 I 帧包格式错误 */ |
| | | ERR_SERVER_CENTER_I_FRAME_INVALID_PACKET: -102025, |
| | | /** 请求 I 帧目标用户不存在 */ |
| | | ERR_SERVER_CENTER_I_FRAME_DEST_USER_NOT_EXIST: -102026, |
| | | /** 请求 I 帧房间用户太多 */ |
| | | ERR_SERVER_CENTER_I_FRAME_ROOM_TOO_BIG: -102027, |
| | | /** 请求 I 帧参数错误 */ |
| | | ERR_SERVER_CENTER_I_FRAME_RPS_INVALID_PARAMETER: -102028, |
| | | /** 房间号非法 */ |
| | | ERR_SERVER_CENTER_INVALID_ROOM_ID: -102029, |
| | | /** 房间号超过限制 */ |
| | | ERR_SERVER_CENTER_ROOM_ID_TOO_LONG: -102030, |
| | | /** 房间满员 */ |
| | | ERR_SERVER_CENTER_ROOM_FULL: -102052, |
| | | /** json串解析失败 */ |
| | | ERR_SERVER_CENTER_DECODE_JSON_FAIL: -102053, |
| | | /** 未定义命令字 */ |
| | | ERR_SERVER_CENTER_UNKNOWN_SUB_CMD: -102054, |
| | | /** 未定义角色 */ |
| | | ERR_SERVER_CENTER_INVALID_ROLE: -102055, |
| | | /** 代理机超出限制 */ |
| | | ERR_SERVER_CENTER_REACH_PROXY_MAX: -102056, |
| | | //add by sunlitwang begin |
| | | /** 无法保存用户自定义recordId */ |
| | | ERR_SERVER_CENTER_RECORDID_STORE: -102057, |
| | | /** Protobuf序列化错误 */ |
| | | ERR_SERVER_CENTER_PB_SERIALIZE: -102058, |
| | | // https://cloud.tencent.com/document/product/269/1671#.E5.B8.90.E5.8F.B7.E7.B3.BB.E7.BB.9F , 帐号系统, 主要是70000 - 79999之间. |
| | | // 在请求 token 过程中,出现账号错误,SSO 返回的错误码,原为正数,现将其转换为负数。 |
| | | /** sig 过期,请尝试重新生成。如果是刚生成,就过期,请检查有效期填写的是否过小,或者填的 0 */ |
| | | ERR_SERVER_SSO_SIG_EXPIRED: -70001, |
| | | /** sig 校验失败,请确认下 sig 内容是否被截断,如缓冲区长度不够导致的内容截断 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_1: -70003, |
| | | /** sig 校验失败,请确认下 sig 内容是否被截断,如缓冲区长度不够导致的内容截断 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_2: -70004, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_3: -70005, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_4: -70006, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_5: -70007, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_6: -70008, |
| | | /** 用业务公钥验证 sig 失败,请确认生成的 usersig 使用的私钥和 sdkAppId 是否对应 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_7: -70009, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_8: -70010, |
| | | /** sig 中 identifier 与请求时的 identifier 不匹配,请检查登录时填写的 identifier 与 sig 中的是否一致 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_ID_NOT_MATCH: -70013, |
| | | /** sig 中 sdkAppId 与请求时的 sdkAppId 不匹配,请检查登录时填写的 sdkAppId 与 sig 中的是否一致 */ |
| | | ERR_SERVER_SSO_APPID_NOT_MATCH: -70014, |
| | | /** 内部第三方票据验证超时,请重试,如多次重试不成功,请@TLS 帐号支持,QQ 3268519604 */ |
| | | ERR_SERVER_SSO_VERIFICATION_EXPIRED: -70017, |
| | | /** 内部第三方票据验证超时,请重试,如多次重试不成功,请@TLS 帐号支持,QQ 3268519604 */ |
| | | ERR_SERVER_SSO_VERIFICATION_FAILED: -70018, |
| | | /** sdkAppId 未找到,请确认是否已经在腾讯云上配置 */ |
| | | ERR_SERVER_SSO_APPID_NOT_FOUND: -70020, |
| | | /** 帐号已被拉入黑名单,请联系 TLS 帐号支持 QQ 3268519604 */ |
| | | ERR_SERVER_SSO_ACCOUNT_IN_BLACKLIST: -70051, |
| | | /** usersig 已经失效,请重新生成,再次尝试 */ |
| | | ERR_SERVER_SSO_SIG_INVALID: -70052, |
| | | /** 安全原因被限制 */ |
| | | ERR_SERVER_SSO_LIMITED_BY_SECURITY: -70114, |
| | | /** 登录状态无效,请使用 usersig 重新鉴权 */ |
| | | ERR_SERVER_SSO_INVALID_LOGIN_STATUS: -70221, |
| | | /** sdkAppId 填写错误 */ |
| | | ERR_SERVER_SSO_APPID_ERROR: -70252, |
| | | /** 票据校验失败,请检查各项参数是否正确 */ |
| | | ERR_SERVER_SSO_TICKET_VERIFICATION_FAILED: -70346, |
| | | /** 票据因过期原因校验失败 */ |
| | | ERR_SERVER_SSO_TICKET_EXPIRED: -70347, |
| | | /** 创建账号数量超过已购买预付费数量限制 */ |
| | | ERR_SERVER_SSO_ACCOUNT_EXCEED_PURCHASES: -70398, |
| | | /** 服务器内部错误,请重试 */ |
| | | ERR_SERVER_SSO_INTERNAL_ERROR: -70500, |
| | | }; |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // (二)错误码(警告) |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * @memberof ErrorCode |
| | | * @typedef 错误码(警告) |
| | | * @description SDK 错误码(警告)对照表 |
| | | * | 符号 | 值 | 含义 | |
| | | * |---|---|---| |
| | | * |WARNING_HW_ENCODER_START_FAIL|1103|硬编码启动出现问题,自动切换到软编码| |
| | | * |WARNING_VIDEO_ENCODER_SW_TO_HW|1107|当前 CPU 使用率太高,无法满足软件编码需求,自动切换到硬件编码| |
| | | * |WARNING_INSUFFICIENT_CAPTURE_FPS|1108|摄像头采集帧率不足,部分自带美颜算法的 Android 手机上会出现| |
| | | * |WARNING_SW_ENCODER_START_FAIL|1109|软编码启动失败| |
| | | * |WARNING_REDUCE_CAPTURE_RESOLUTION|1110|摄像头采集分辨率被降低,以满足当前帧率和性能最优解。| |
| | | * |WARNING_VIDEO_FRAME_DECODE_FAIL|2101|当前视频帧解码失败| |
| | | * |WARNING_AUDIO_FRAME_DECODE_FAIL|2102|当前音频帧解码失败| |
| | | * |WARNING_VIDEO_PLAY_LAG|2105|当前视频播放出现卡顿| |
| | | * |WARNING_HW_DECODER_START_FAIL|2106|硬解启动失败,采用软解码| |
| | | * |WARNING_VIDEO_DECODER_HW_TO_SW|2108|当前流硬解第一个 I 帧失败,SDK 自动切软解| |
| | | * |WARNING_SW_DECODER_START_FAIL|2109|软解码器启动失败| |
| | | * |WARNING_VIDEO_RENDER_FAIL|2110|视频渲染失败| |
| | | * |WARNING_AUDIO_RECORDING_WRITE_FAIL|7001|音频录制写入文件失败| |
| | | * |WARNING_ROOM_DISCONNECT|5101|网络断开连接| |
| | | * |WARNING_IGNORE_UPSTREAM_FOR_AUDIENCE|6001|当前是观众角色,忽略上行音视频数据| |
| | | */ |
| | | export const TXLiteAVWarning = { |
| | | /** 硬编码启动出现问题,自动切换到软编码 */ |
| | | WARNING_HW_ENCODER_START_FAIL: 1103, |
| | | /** 当前 CPU 使用率太高,无法满足软件编码需求,自动切换到硬件编码 */ |
| | | WARNING_VIDEO_ENCODER_SW_TO_HW: 1107, |
| | | /** 摄像头采集帧率不足,部分自带美颜算法的 Android 手机上会出现 */ |
| | | WARNING_INSUFFICIENT_CAPTURE_FPS: 1108, |
| | | /** 软编码启动失败 */ |
| | | WARNING_SW_ENCODER_START_FAIL: 1109, |
| | | /** 摄像头采集分辨率被降低,以满足当前帧率和性能最优解。 */ |
| | | WARNING_REDUCE_CAPTURE_RESOLUTION: 1110, |
| | | /** 当前视频帧解码失败 */ |
| | | WARNING_VIDEO_FRAME_DECODE_FAIL: 2101, |
| | | /** 当前音频帧解码失败 */ |
| | | WARNING_AUDIO_FRAME_DECODE_FAIL: 2102, |
| | | /** 当前视频播放出现卡顿 */ |
| | | WARNING_VIDEO_PLAY_LAG: 2105, |
| | | /** 硬解启动失败,采用软解码 */ |
| | | WARNING_HW_DECODER_START_FAIL: 2106, |
| | | /** 当前流硬解第一个 I 帧失败,SDK 自动切软解 */ |
| | | WARNING_VIDEO_DECODER_HW_TO_SW: 2108, |
| | | /** 软解码器启动失败 */ |
| | | WARNING_SW_DECODER_START_FAIL: 2109, |
| | | /** 视频渲染失败 */ |
| | | WARNING_VIDEO_RENDER_FAIL: 2110, |
| | | /** 音频录制写入文件失败 */ |
| | | WARNING_AUDIO_RECORDING_WRITE_FAIL: 7001, |
| | | /** 网络断开连接 */ |
| | | WARNING_ROOM_DISCONNECT: 5101, |
| | | /** 当前是观众角色,忽略上行音视频数据 */ |
| | | WARNING_IGNORE_UPSTREAM_FOR_AUDIENCE: 6001, |
| | | /** 网络状况不佳:上行带宽太小,上传数据受阻 */ |
| | | WARNING_NET_BUSY: 1101, |
| | | /** 直播,网络断连, 已启动自动重连(自动重连连续失败超过三次会放弃) */ |
| | | WARNING_RTMP_SERVER_RECONNECT: 1102, |
| | | /** 直播,网络断连, 已启动自动重连(自动重连连续失败超过三次会放弃) */ |
| | | WARNING_LIVE_STREAM_SERVER_RECONNECT: 2103, |
| | | /** 网络来包不稳:可能是下行带宽不足,或由于主播端出流不均匀 */ |
| | | WARNING_RECV_DATA_LAG: 2104, |
| | | /** 直播,DNS 解析失败 */ |
| | | WARNING_RTMP_DNS_FAIL: 3001, |
| | | /** 直播,服务器连接失败 */ |
| | | WARNING_RTMP_SEVER_CONN_FAIL: 3002, |
| | | /** 直播,与 RTMP 服务器握手失败 */ |
| | | WARNING_RTMP_SHAKE_FAIL: 3003, |
| | | /** 直播,服务器主动断开 */ |
| | | WARNING_RTMP_SERVER_BREAK_CONNECT: 3004, |
| | | /** 直播,RTMP 读/写失败,将会断开连接 */ |
| | | WARNING_RTMP_READ_WRITE_FAIL: 3005, |
| | | /** 直播,RTMP 写失败(SDK 内部错误码,不会对外抛出) */ |
| | | WARNING_RTMP_WRITE_FAIL: 3006, |
| | | /** 直播,RTMP 读失败(SDK 内部错误码,不会对外抛出) */ |
| | | WARNING_RTMP_READ_FAIL: 3007, |
| | | /** 直播,超过30s 没有数据发送,主动断开连接 */ |
| | | WARNING_RTMP_NO_DATA: 3008, |
| | | /** 直播,connect 服务器调用失败(SDK 内部错误码,不会对外抛出) */ |
| | | WARNING_PLAY_LIVE_STREAM_INFO_CONNECT_FAIL: 3009, |
| | | /** 直播,连接失败,该流地址无视频(SDK 内部错误码,不会对外抛出) */ |
| | | WARNING_NO_STEAM_SOURCE_FAIL: 3010, |
| | | /** 网络断连,已启动自动重连 */ |
| | | WARNING_ROOM_RECONNECT: 5102, |
| | | /** 网络状况不佳:上行带宽太小,上传数据受阻 */ |
| | | WARNING_ROOM_NET_BUSY: 5103, |
| | | }; |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // (三)JS 封装层抛出的异常(严重) |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * @namespace ErrorCode |
| | | * @description 错误码 |
| | | */ |
| | | export const TXLiteJSError = { |
| | | /** |
| | | * 未知错误 |
| | | * @default 0xFFFF |
| | | * @memberof module:ErrorCode |
| | | */ |
| | | UNKNOWN: 0xffff, |
| | | /** |
| | | * 无效参数 |
| | | * |
| | | * @default 0x1000 |
| | | * @memberof module:ErrorCode |
| | | */ |
| | | INVALID_PARAMETER: 0x1000, |
| | | /** |
| | | * 非法操作 |
| | | * |
| | | * @default 0x1001 |
| | | * @memberof module:ErrorCode |
| | | */ |
| | | INVALID_OPERATION: 0x1001, |
| | | }; |
| | | const getErrorName = function (code) { |
| | | for (let key in TXLiteJSError) { |
| | | if (TXLiteJSError[key] === code) { |
| | | return key; |
| | | } |
| | | } |
| | | return 'UNKNOWN'; |
| | | }; |
| | | /** |
| | | * TrtcError 错误对象<br> |
| | | * @extends Error |
| | | * @namespace ErrorCode |
| | | */ |
| | | class TrtcError extends Error { |
| | | constructor({ code = TXLiteJSError.UNKNOWN, message, extraInfo }) { |
| | | if (extraInfo) { |
| | | const tempError = { |
| | | errCode: code, |
| | | errMsg: message, |
| | | extraInfo: Object.assign(Object.assign({}, extraInfo), { errCodeUrl: errorCodeUrl }), |
| | | }; |
| | | super(JSON.stringify(tempError)); |
| | | } |
| | | else { |
| | | super(message + |
| | | ` <${getErrorName(code)} 0x${code.toString(16)}>. Refer to: ${errorCodeUrl}`); |
| | | } |
| | | this.errCode = code; |
| | | this.errMsg = message; |
| | | this.extraInfo = Object.assign(Object.assign({}, extraInfo), { errCodeUrl: errorCodeUrl }); |
| | | } |
| | | /** |
| | | * 获取错误码<br> |
| | | * 详细错误码列表参见 {@link module:ErrorCode ErrorCode} |
| | | * @memberof TrtcError |
| | | */ |
| | | getCode() { |
| | | return this.errCode; |
| | | } |
| | | } |
| | | export default TrtcError; |
| | | export function generateError_(error, code = TXLiteJSError.UNKNOWN, extraInfo) { |
| | | return new TrtcError({ |
| | | code: error.code || code, |
| | | message: `${NAME.LOG_PREFIX}${error.message}`, |
| | | extraInfo, |
| | | }); |
| | | } |
| | | ; |
| New file |
| | |
| | | /** |
| | | * TRTC 关键类型定义<br> |
| | | * @description 分辨率、质量等级等枚举和常量值的定义 |
| | | */ |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【(一)视频相关枚举值定义】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 视频分辨率<br> |
| | | * 此处仅定义横屏分辨率(如 640 × 360),如需使用竖屏分辨率(如 360 × 640),需要同时指定 VideoResolutionMode 为 Portrait |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoResolution_HACK_JSDOC = { |
| | | /** 宽高比 1:1;分辨率 120x120;建议码率(VideoCall)80kbps; 建议码率(LIVE)120kbps */ |
| | | TRTCVideoResolution_120_120: 1, |
| | | /** 宽高比 1:1 分辨率 160x160;建议码率(VideoCall)100kbps; 建议码率(LIVE)150kbps */ |
| | | TRTCVideoResolution_160_160: 3, |
| | | /** 宽高比 1:1;分辨率 270x270;建议码率(VideoCall)200kbps; 建议码率(LIVE)300kbps */ |
| | | TRTCVideoResolution_270_270: 5, |
| | | /** 宽高比 1:1;分辨率 480x480;建议码率(VideoCall)350kbps; 建议码率(LIVE)500kbps */ |
| | | TRTCVideoResolution_480_480: 7, |
| | | /** 宽高比4:3;分辨率 160x120;建议码率(VideoCall)100kbps; 建议码率(LIVE)150kbps */ |
| | | TRTCVideoResolution_160_120: 50, |
| | | /** 宽高比 4:3;分辨率 240x180;建议码率(VideoCall)150kbps; 建议码率(LIVE)250kbps */ |
| | | TRTCVideoResolution_240_180: 52, |
| | | /** 宽高比 4:3;分辨率 280x210;建议码率(VideoCall)200kbps; 建议码率(LIVE)300kbps */ |
| | | TRTCVideoResolution_280_210: 54, |
| | | /** 宽高比 4:3;分辨率 320x240;建议码率(VideoCall)250kbps; 建议码率(LIVE)375kbps */ |
| | | TRTCVideoResolution_320_240: 56, |
| | | /** 宽高比 4:3;分辨率 400x300;建议码率(VideoCall)300kbps; 建议码率(LIVE)450kbps */ |
| | | TRTCVideoResolution_400_300: 58, |
| | | /** 宽高比 4:3;分辨率 480x360;建议码率(VideoCall)400kbps; 建议码率(LIVE)600kbps */ |
| | | TRTCVideoResolution_480_360: 60, |
| | | /** 宽高比 4:3;分辨率 640x480;建议码率(VideoCall)600kbps; 建议码率(LIVE)900kbps */ |
| | | TRTCVideoResolution_640_480: 62, |
| | | /** 宽高比 4:3;分辨率 960x720;建议码率(VideoCall)1000kbps; 建议码率(LIVE)1500kbps */ |
| | | TRTCVideoResolution_960_720: 64, |
| | | /** 宽高比 16:9;分辨率 160x90;建议码率(VideoCall)150kbps; 建议码率(LIVE)250kbps */ |
| | | TRTCVideoResolution_160_90: 100, |
| | | /** 宽高比 16:9;分辨率 256x144;建议码率(VideoCall)200kbps; 建议码率(LIVE)300kbps */ |
| | | TRTCVideoResolution_256_144: 102, |
| | | /** 宽高比 16:9;分辨率 320x180;建议码率(VideoCall)250kbps; 建议码率(LIVE)400kbps */ |
| | | TRTCVideoResolution_320_180: 104, |
| | | /** 宽高比 16:9;分辨率 480x270;建议码率(VideoCall)350kbps; 建议码率(LIVE)550kbps */ |
| | | TRTCVideoResolution_480_270: 106, |
| | | /** 宽高比 16:9;分辨率 640x360;建议码率(VideoCall)500kbps; 建议码率(LIVE)900kbps */ |
| | | TRTCVideoResolution_640_360: 108, |
| | | /** 宽高比 16:9;分辨率 960x540;建议码率(VideoCall)850kbps; 建议码率(LIVE)1300kbps */ |
| | | TRTCVideoResolution_960_540: 110, |
| | | /** 宽高比 16:9;分辨率 1280x720;建议码率(VideoCall)1200kbps; 建议码率(LIVE)1800kbps */ |
| | | TRTCVideoResolution_1280_720: 112, |
| | | /** 宽高比 16:9;分辨率 1920x1080;建议码率(VideoCall)2000kbps; 建议码率(LIVE)3000kbps */ |
| | | TRTCVideoResolution_1920_1080: 114, |
| | | }; |
| | | export var TRTCVideoResolution; |
| | | (function (TRTCVideoResolution) { |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_120_120"] = 1] = "TRTCVideoResolution_120_120"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_160_160"] = 3] = "TRTCVideoResolution_160_160"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_270_270"] = 5] = "TRTCVideoResolution_270_270"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_480_480"] = 7] = "TRTCVideoResolution_480_480"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_160_120"] = 50] = "TRTCVideoResolution_160_120"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_240_180"] = 52] = "TRTCVideoResolution_240_180"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_280_210"] = 54] = "TRTCVideoResolution_280_210"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_320_240"] = 56] = "TRTCVideoResolution_320_240"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_400_300"] = 58] = "TRTCVideoResolution_400_300"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_480_360"] = 60] = "TRTCVideoResolution_480_360"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_640_480"] = 62] = "TRTCVideoResolution_640_480"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_960_720"] = 64] = "TRTCVideoResolution_960_720"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_160_90"] = 100] = "TRTCVideoResolution_160_90"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_256_144"] = 102] = "TRTCVideoResolution_256_144"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_320_180"] = 104] = "TRTCVideoResolution_320_180"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_480_270"] = 106] = "TRTCVideoResolution_480_270"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_640_360"] = 108] = "TRTCVideoResolution_640_360"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_960_540"] = 110] = "TRTCVideoResolution_960_540"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_1280_720"] = 112] = "TRTCVideoResolution_1280_720"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_1920_1080"] = 114] = "TRTCVideoResolution_1920_1080"; |
| | | })(TRTCVideoResolution || (TRTCVideoResolution = {})); |
| | | /** |
| | | * 视频分辨率模式<br> |
| | | * TRTCVideoResolution 中仅定义了横屏分辨率(如 640 × 360),如需使用竖屏分辨率(如 360 × 640),需要同时指定 TRTCVideoResolutionMode 为 Portrait |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoResolutionMode_HACK_JSDOC = { |
| | | /** 横屏分辨率 */ |
| | | TRTCVideoResolutionModeLandscape: 0, |
| | | /** 竖屏分辨率 */ |
| | | TRTCVideoResolutionModePortrait: 1, |
| | | }; |
| | | export var TRTCVideoResolutionMode; |
| | | (function (TRTCVideoResolutionMode) { |
| | | TRTCVideoResolutionMode[TRTCVideoResolutionMode["TRTCVideoResolutionModeLandscape"] = 0] = "TRTCVideoResolutionModeLandscape"; |
| | | TRTCVideoResolutionMode[TRTCVideoResolutionMode["TRTCVideoResolutionModePortrait"] = 1] = "TRTCVideoResolutionModePortrait"; |
| | | })(TRTCVideoResolutionMode || (TRTCVideoResolutionMode = {})); |
| | | ; |
| | | /** |
| | | * 视频流类型<br> |
| | | * TRTC 内部有三种不同的音视频流,分别是: |
| | | * - 高清大画面:一般用来传输摄像头的视频数据 |
| | | * - 低清小画面:小画面和大画面的内容相互,但是分辨率和码率都比大画面低,因此清晰度也更低 |
| | | * - 辅流画面:一般用于屏幕分享,同一时间在同一个房间中只允许一个用户发布辅流视频,其他用户必须要等该用户关闭之后才能发布自己的辅流 |
| | | * |
| | | * **Note:** |
| | | * - 不支持单独开启低清小画面,小画面必须依附于大画面而存在,SDK 会自动设定低清小画面的分辨率和码率 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoStreamType_HACK_JSDOC = { |
| | | /** 大画面视频流 */ |
| | | TRTCVideoStreamTypeBig: 0, |
| | | /** 小画面视频流 */ |
| | | TRTCVideoStreamTypeSmall: 1, |
| | | /** 辅流(屏幕分享) */ |
| | | TRTCVideoStreamTypeSub: 2, |
| | | }; |
| | | export var TRTCVideoStreamType; |
| | | (function (TRTCVideoStreamType) { |
| | | TRTCVideoStreamType[TRTCVideoStreamType["TRTCVideoStreamTypeBig"] = 0] = "TRTCVideoStreamTypeBig"; |
| | | TRTCVideoStreamType[TRTCVideoStreamType["TRTCVideoStreamTypeSmall"] = 1] = "TRTCVideoStreamTypeSmall"; |
| | | TRTCVideoStreamType[TRTCVideoStreamType["TRTCVideoStreamTypeSub"] = 2] = "TRTCVideoStreamTypeSub"; |
| | | })(TRTCVideoStreamType || (TRTCVideoStreamType = {})); |
| | | /** |
| | | * 画面来源<br> |
| | | * TRTC 内部有两种不同的画面来源,分别是: |
| | | * - TRTCSnapshotSourceTypeStream: 视频流画面 |
| | | * - TRTCSnapshotSourceTypeView: 视频渲染画面 |
| | | * |
| | | * **Note:** |
| | | * - 截取视频流画面(TRTCSnapshotSourceTypeStream)一般更清晰。 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCSnapshotSourceType_HACK_JSDOC = { |
| | | /** 视频流画面 */ |
| | | TRTCSnapshotSourceTypeStream: 0, |
| | | /** 视频渲染画面 */ |
| | | TRTCSnapshotSourceTypeView: 1, |
| | | }; |
| | | export var TRTCSnapshotSourceType; |
| | | (function (TRTCSnapshotSourceType) { |
| | | TRTCSnapshotSourceType[TRTCSnapshotSourceType["TRTCSnapshotSourceTypeStream"] = 0] = "TRTCSnapshotSourceTypeStream"; |
| | | TRTCSnapshotSourceType[TRTCSnapshotSourceType["TRTCSnapshotSourceTypeView"] = 1] = "TRTCSnapshotSourceTypeView"; |
| | | })(TRTCSnapshotSourceType || (TRTCSnapshotSourceType = {})); |
| | | /** |
| | | * 视频画面填充模式<br> |
| | | * 如果画面的显示分辨率不等于画面的原始分辨率,就需要您设置画面的填充模式: |
| | | * - TRTCVideoFillMode_Fill,图像铺满屏幕,超出显示视窗的视频部分将被截掉,所以画面显示可能不完整。 |
| | | * - TRTCVideoFillMode_Fit,图像长边填满屏幕,短边区域会被填充黑色,但画面的内容肯定是完整的。 |
| | | * - TRTCVideoFillMode_ScaleFill,缩放填充模式,即无论画面的宽高比,都会被拉伸或压缩以完全填充显示区域,此模式下画面宽高比可能会被改变,导致渲染画面变形 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoFillMode_HACK_JSDOC = { |
| | | /** 图像铺满屏幕,超出显示视窗的视频部分将被截掉 */ |
| | | TRTCVideoFillMode_Fill: 0, |
| | | /** 图像长边填满屏幕,短边区域会被填充黑色 */ |
| | | TRTCVideoFillMode_Fit: 1, |
| | | /** 缩放填充模式,即无论画面的宽高比,都会被拉伸或压缩以完全填充显示区域 */ |
| | | TRTCVideoFillMode_ScaleFill: 2, |
| | | }; |
| | | export var TRTCVideoFillMode; |
| | | (function (TRTCVideoFillMode) { |
| | | TRTCVideoFillMode[TRTCVideoFillMode["TRTCVideoFillMode_Fill"] = 0] = "TRTCVideoFillMode_Fill"; |
| | | TRTCVideoFillMode[TRTCVideoFillMode["TRTCVideoFillMode_Fit"] = 1] = "TRTCVideoFillMode_Fit"; |
| | | TRTCVideoFillMode[TRTCVideoFillMode["TRTCVideoFillMode_ScaleFill"] = 2] = "TRTCVideoFillMode_ScaleFill"; |
| | | })(TRTCVideoFillMode || (TRTCVideoFillMode = {})); |
| | | ; |
| | | /** |
| | | * 视频画面旋转方向<br> |
| | | * TRTC SDK 提供了对本地和远程画面的旋转角度设置 API,如下的旋转角度都是指顺时针方向的。 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoRotation_HACK_JSDOC = { |
| | | /** 顺时针旋转0度 */ |
| | | TRTCVideoRotation_0: 0, |
| | | /** 顺时针旋转90度 */ |
| | | TRTCVideoRotation_90: 1, |
| | | /** 顺时针旋转180度 */ |
| | | TRTCVideoRotation_180: 2, |
| | | /** 顺时针旋转270度 */ |
| | | TRTCVideoRotation_270: 3, |
| | | }; |
| | | export var TRTCVideoRotation; |
| | | (function (TRTCVideoRotation) { |
| | | TRTCVideoRotation[TRTCVideoRotation["TRTCVideoRotation_0"] = 0] = "TRTCVideoRotation_0"; |
| | | TRTCVideoRotation[TRTCVideoRotation["TRTCVideoRotation_90"] = 1] = "TRTCVideoRotation_90"; |
| | | TRTCVideoRotation[TRTCVideoRotation["TRTCVideoRotation_180"] = 2] = "TRTCVideoRotation_180"; |
| | | TRTCVideoRotation[TRTCVideoRotation["TRTCVideoRotation_270"] = 3] = "TRTCVideoRotation_270"; |
| | | })(TRTCVideoRotation || (TRTCVideoRotation = {})); |
| | | /** |
| | | * 画面渲染镜像类型<br> |
| | | * TRTC 的画面镜像提供下列设置模式 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoMirrorType_HACK_JSDOC = { |
| | | /** 只适用于移动端, 本地预览时,前置摄像头镜像,后置摄像头不镜像 */ |
| | | TRTCVideoMirrorType_Auto: 0, |
| | | /** 所有画面均镜像 */ |
| | | TRTCVideoMirrorType_Enable: 1, |
| | | /** 所有画面均不镜像 */ |
| | | TRTCVideoMirrorType_Disable: 2 |
| | | }; |
| | | export var TRTCVideoMirrorType; |
| | | (function (TRTCVideoMirrorType) { |
| | | TRTCVideoMirrorType[TRTCVideoMirrorType["TRTCVideoMirrorType_Auto"] = 0] = "TRTCVideoMirrorType_Auto"; |
| | | TRTCVideoMirrorType[TRTCVideoMirrorType["TRTCVideoMirrorType_Enable"] = 1] = "TRTCVideoMirrorType_Enable"; |
| | | TRTCVideoMirrorType[TRTCVideoMirrorType["TRTCVideoMirrorType_Disable"] = 2] = "TRTCVideoMirrorType_Disable"; |
| | | })(TRTCVideoMirrorType || (TRTCVideoMirrorType = {})); |
| | | /** |
| | | * 美颜(磨皮)算法<br> |
| | | * TRTC SDK 内置了多种不同的磨皮算法,您可以选择最适合您产品定位的方案。 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCBeautyStyle_HACK_JSDOC = { |
| | | /** 光滑,算法比较激进,磨皮效果比较明显,适用于秀场直播 */ |
| | | TRTCBeautyStyleSmooth: 0, |
| | | /** 自然,算法更多地保留了面部细节,磨皮效果更加自然,适用于绝大多数直播场景 */ |
| | | TRTCBeautyStyleNature: 1, |
| | | /** 优图,由优图实验室提供,磨皮效果介于光滑和自然之间,比光滑保留更多皮肤细节,比自然磨皮程度更高 */ |
| | | TRTCBeautyStylePitu: 2, |
| | | }; |
| | | export var TRTCBeautyStyle; |
| | | (function (TRTCBeautyStyle) { |
| | | TRTCBeautyStyle[TRTCBeautyStyle["TRTCBeautyStyleSmooth"] = 0] = "TRTCBeautyStyleSmooth"; |
| | | TRTCBeautyStyle[TRTCBeautyStyle["TRTCBeautyStyleNature"] = 1] = "TRTCBeautyStyleNature"; |
| | | TRTCBeautyStyle[TRTCBeautyStyle["TRTCBeautyStylePitu"] = 2] = "TRTCBeautyStylePitu"; |
| | | })(TRTCBeautyStyle || (TRTCBeautyStyle = {})); |
| | | /** |
| | | * 背景音效<br> |
| | | * @enum {Number} |
| | | */ |
| | | export class AudioMusicParam { |
| | | constructor(id, path, loopCount, publish, isShortFile, startTimeMS, endTimeMS) { |
| | | this.id = id; |
| | | this.path = path; |
| | | this.loopCount = loopCount; |
| | | this.publish = publish; |
| | | this.isShortFile = isShortFile; |
| | | this.startTimeMS = startTimeMS; |
| | | this.endTimeMS = endTimeMS; |
| | | } |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【(二)网络相关枚举值定义】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 应用场景<br> |
| | | * TRTC 可用于视频会议和在线直播等多种应用场景,针对不同的应用场景,TRTC SDK 的内部会进行不同的优化配置: |
| | | * - TRTCAppSceneVideoCall :视频通话场景,适合[1对1视频通话]、[300人视频会议]、[在线问诊]、[视频聊天]、[远程面试]等。 |
| | | * - TRTCAppSceneLIVE :视频互动直播,适合[视频低延时直播]、[十万人互动课堂]、[视频直播 PK]、[视频相亲房]、[互动课堂]、[远程培训]、[超大型会议]等。 |
| | | * - TRTCAppSceneAudioCall :语音通话场景,适合[1对1语音通话]、[300人语音会议]、[语音聊天]、[语音会议]、[在线狼人杀]等。 |
| | | * - TRTCAppSceneVoiceChatRoom:语音互动直播,适合:[语音低延时直播]、[语音直播连麦]、[语聊房]、[K 歌房]、[FM 电台]等。 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCAppScene_HACK_JSDOC = { |
| | | /** |
| | | * 视频通话场景,支持720P、1080P高清画质,单个房间最多支持300人同时在线,最高支持50人同时发言。<br> |
| | | * 适合:[视频低延时直播]、[十万人互动课堂]、[视频直播 PK]、[视频相亲房]、[互动课堂]、[远程培训]、[超大型会议]等。<br> |
| | | * 注意:此场景下,您必须通过 TRTCParams 中的 role 字段指定当前用户的角色。 |
| | | */ |
| | | TRTCAppSceneVideoCall: 0, |
| | | /** |
| | | * 视频互动直播,支持平滑上下麦,切换过程无需等待,主播延时小于300ms;支持十万级别观众同时播放,播放延时低至1000ms。<br> |
| | | * 在线直播场景,内部编码器和网络协议优化侧重性能和兼容性,性能和清晰度表现更佳。 |
| | | */ |
| | | TRTCAppSceneLIVE: 1, |
| | | /** |
| | | * 语音通话场景,支持 48kHz,支持双声道。单个房间最多支持300人同时在线,最高支持50人同时发言。<br> |
| | | * 适合:[1对1语音通话]、[300人语音会议]、[语音聊天]、[语音会议]、[在线狼人杀]等。 |
| | | */ |
| | | TRTCAppSceneAudioCall: 2, |
| | | /** |
| | | * 语音互动直播,支持平滑上下麦,切换过程无需等待,主播延时小于300ms;支持十万级别观众同时播放,播放延时低至1000ms。<br> |
| | | * 适合:[语音低延时直播]、[语音直播连麦]、[语聊房]、[K 歌房]、[FM 电台]等。<br> |
| | | * 注意:此场景下,您必须通过 TRTCParams 中的 role 字段指定当前用户的角色。 |
| | | */ |
| | | TRTCAppSceneVoiceChatRoom: 3, |
| | | }; |
| | | export var TRTCAppScene; |
| | | (function (TRTCAppScene) { |
| | | TRTCAppScene[TRTCAppScene["TRTCAppSceneVideoCall"] = 0] = "TRTCAppSceneVideoCall"; |
| | | TRTCAppScene[TRTCAppScene["TRTCAppSceneLIVE"] = 1] = "TRTCAppSceneLIVE"; |
| | | TRTCAppScene[TRTCAppScene["TRTCAppSceneAudioCall"] = 2] = "TRTCAppSceneAudioCall"; |
| | | TRTCAppScene[TRTCAppScene["TRTCAppSceneVoiceChatRoom"] = 3] = "TRTCAppSceneVoiceChatRoom"; |
| | | })(TRTCAppScene || (TRTCAppScene = {})); |
| | | /** |
| | | * 角色,仅适用于直播场景(TRTCAppSceneLIVE 和 TRTCAppSceneVoiceChatRoom)<br> |
| | | * 在直播场景中,多数用户只是观众,只有个别用户是主播,这种角色区分可以有利于 TRTC 进行更好的定向优化。 |
| | | * - Anchor:主播,可以上行视频和音频,一个房间里最多支持50个主播同时上行音视频。 |
| | | * - Audience:观众,只能观看,不能上行视频和音频,一个房间里的观众人数没有上限。 |
| | | * |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCRoleType_HACK_JSDOC = { |
| | | /** 主播 */ |
| | | TRTCRoleAnchor: 20, |
| | | /** 观众 */ |
| | | TRTCRoleAudience: 21, |
| | | }; |
| | | export var TRTCRoleType; |
| | | (function (TRTCRoleType) { |
| | | TRTCRoleType[TRTCRoleType["TRTCRoleAnchor"] = 20] = "TRTCRoleAnchor"; |
| | | TRTCRoleType[TRTCRoleType["TRTCRoleAudience"] = 21] = "TRTCRoleAudience"; |
| | | })(TRTCRoleType || (TRTCRoleType = {})); |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【(三)音频相关枚举值定义】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 音频质量<br> |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCAudioQuality_HACK_JSDOC = { |
| | | /** 人声模式:适用于以人声沟通为主的应用场景,该模式下音频传输的抗性较强,TRTC 会通过各种人声处理技术保障在弱网络环境下的流畅度最佳 */ |
| | | TRTCAudioQualitySpeech: 1, |
| | | /** 标准模式(或者默认模式):介于 Speech 和 Music 之间的档位,对音乐的还原度比人声模式要好,但传输数据量比音乐模式要低很多,对各种场景均有不错的适应性,如无特殊需求推荐选择之。 */ |
| | | TRTCAudioQualityDefault: 2, |
| | | /** 音乐模式:适用于对声乐要求很苛刻的场景,该模式下音频传输的数据量很大,TRTC 会通过各项技术确保音乐信号在各频段均能获得高保真的细节还原度 */ |
| | | TRTCAudioQualityMusic: 3 |
| | | }; |
| | | export var TRTCAudioQuality; |
| | | (function (TRTCAudioQuality) { |
| | | TRTCAudioQuality[TRTCAudioQuality["TRTCAudioQualitySpeech"] = 1] = "TRTCAudioQualitySpeech"; |
| | | TRTCAudioQuality[TRTCAudioQuality["TRTCAudioQualityDefault"] = 2] = "TRTCAudioQualityDefault"; |
| | | TRTCAudioQuality[TRTCAudioQuality["TRTCAudioQualityMusic"] = 3] = "TRTCAudioQualityMusic"; |
| | | })(TRTCAudioQuality || (TRTCAudioQuality = {})); |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【(四)TRTC 核心类型定义】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 进房相关参数<br> |
| | | * 只有该参数填写正确,才能顺利调用 enterRoom 进入 roomId 所指定的音视频房间。 |
| | | * @param {Number} sdkAppId - 【字段含义】应用标识(必填),腾讯视频云基于 sdkAppId 完成计费统计。<br> |
| | | * 【推荐取值】在腾讯云 [TRTC 控制台](https://console.cloud.tencent.com/rav/) 中创建应用,之后可以在账号信息页面中得到该 ID。<br> |
| | | * @param {String} userId - 【字段含义】用户标识(必填)。当前用户的 userId,相当于用户名,UTF-8编码。<br> |
| | | * 【推荐取值】如果一个用户在您的账号系统中的 ID 为“abc”,则 userId 即可设置为“abc”。<br> |
| | | * @param {String} userSig - 【字段含义】用户签名(必填),当前 userId 对应的验证签名,相当于登录密码。<br> |
| | | * 【推荐取值】请参考 [如何计算UserSig](https://cloud.tencent.com/document/product/647/17275)。<br> |
| | | * @param {Number} roomId - 【字段含义】房间号码(必填),指定房间号,在同一个房间里的用户(userId)可以彼此看到对方并进行视频通话, roomId 和 strRoomId 必须填一个, 若您选用 strRoomId,则 roomId 需要填写为0。<br> |
| | | * 【推荐取值】您可以随意指定,但请不要重复,如果您的用户账号 ID 是数字类型的,可以直接用创建者的用户 ID 作为 roomId。<br> |
| | | * @param {String} strRoomId - 【字段含义】字符串房间号码(选填),roomId 和 strRoomId 必须填一个。若两者都填,则优先选择 roomId。<br> |
| | | * 【推荐取值】您可以随意指定,但请不要重复。<br> |
| | | * @param {TRTCRoleType} role - 【字段含义】直播场景下的角色,仅适用于直播场景(TRTCAppSceneLIVE 和 TRTCAppSceneVoiceChatRoom),视频通话场景下指定无效。<br> |
| | | * 【推荐取值】默认值:主播(TRTCRoleAnchor)<br> |
| | | * @param {String} privateMapKey - 【字段含义】房间签名(非必填),如果您希望某个房间只能让特定的某些 userId 进入,就需要使用 privateMapKey 进行权限保护。<br> |
| | | * 【推荐取值】仅建议有高级别安全需求的客户使用,参考文档:[进房权限保护](https://cloud.tencent.com/document/product/647/32240)<br> |
| | | * @param {String} businessInfo - 【字段含义】业务数据(非必填),某些非常用的高级特性才需要用到此字段。<br> |
| | | * 【推荐取值】不建议使用<br> |
| | | * @param {String} streamId - 【字段含义】绑定腾讯云直播 CDN 流 ID[非必填],设置之后,您就可以在腾讯云直播 CDN 上通过标准直播方案(FLV或HLS)播放该用户的音视频流。<br> |
| | | * 【推荐取值】限制长度为64字节,可以不填写,一种推荐的方案是使用 “sdkappid_roomid_userid_main” 作为 streamid,这样比较好辨认且不会在您的多个应用中发生冲突。<br> |
| | | * 【特殊说明】要使用腾讯云直播 CDN,您需要先在[控制台](https://console.cloud.tencent.com/trtc/) 中的功能配置页开启“启动自动旁路直播”开关。<br> |
| | | * 【参考文档】[CDN 旁路直播](https://cloud.tencent.com/document/product/647/16826)。 |
| | | * @param {String} userDefineRecordId - 【字段含义】设置云端录制完成后的回调消息中的 "userdefinerecordid" 字段内容,便于您更方便的识别录制回调。<br> |
| | | * 【推荐取值】限制长度为64字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。<br> |
| | | * 【参考文档】[云端录制](https://cloud.tencent.com/document/product/647/16823)。 |
| | | */ |
| | | export class TRTCParams { |
| | | constructor(sdkAppId, userId, roomId, userSig, strRoomId, privateMapKey, role, businessInfo, streamId, userDefineRecordId) { |
| | | this.sdkAppId = sdkAppId; |
| | | this.userId = userId; |
| | | this.roomId = roomId; |
| | | this.userSig = userSig; |
| | | this.strRoomId = strRoomId; |
| | | this.privateMapKey = privateMapKey; |
| | | this.role = role; |
| | | this.businessInfo = businessInfo; |
| | | this.streamId = streamId; |
| | | this.userDefineRecordId = userDefineRecordId; |
| | | } |
| | | } |
| | | /** |
| | | * 视频编码参数<br> |
| | | * 该设置决定了远端用户看到的画面质量(同时也是云端录制出的视频文件的画面质量)。 |
| | | * @param {TRTCVideoResolution} videoResolution - 【字段含义】 视频分辨率<br> |
| | | * 【推荐取值】 <br> |
| | | * - 视频通话建议选择360 × 640及以下分辨率,resMode 选择 Portrait。<br> |
| | | * - 手机直播建议选择 540 × 960,resMode 选择 Portrait。<br> |
| | | * - Window 和 iMac 建议选择 640 × 360 及以上分辨率,resMode 选择 Landscape。 |
| | | * 【特别说明】 TRTCVideoResolution 默认只能横屏模式的分辨率,例如640 × 360。<br> |
| | | * 如需使用竖屏分辨率,请指定 resMode 为 Portrait,例如640 × 360结合 Portrait 则为360 × 640。<br> |
| | | * @param {TRTCVideoResolutionMode} resMode - 【字段含义】分辨率模式(横屏分辨率 - 竖屏分辨率)<br> |
| | | * 【推荐取值】手机直播建议选择 Portrait,Window 和 Mac 建议选择 Landscape。<br> |
| | | * 【特别说明】如果 videoResolution 指定分辨率 640 × 360,resMode 指定模式为 Portrait,则最终编码出的分辨率为360 × 640。<br> |
| | | * @param {Number} videoFps - 【字段含义】视频采集帧率<br> |
| | | * 【推荐取值】15fps 或 20fps,10fps 以下会有轻微卡顿感,5fps 以下卡顿感明显,20fps 以上的帧率则过于浪费(电影的帧率也只有 24fps)。<br> |
| | | * 【特别说明】很多 Android 手机的前置摄像头并不支持15fps以上的采集帧率,部分过于突出美颜功能的 Android 手机前置摄像头的采集帧率可能低于10fps。<br> |
| | | * @param {Number} videoBitrate - 【字段含义】视频上行码率<br> |
| | | * 【推荐取值】推荐设置请参考本文件前半部分 TRTCVideoResolution 定义处的注释说明<br> |
| | | * 【特别说明】码率太低会导致视频中有很多的马赛克<br> |
| | | * @param {Number} minVideoBitrate -【字段含义】最低视频码率,SDK 会在网络不佳的情况下主动降低视频码率,最低会降至 minVideoBitrate 所设定的数值。 |
| | | * 【推荐取值】<br> |
| | | * - 如果您追求“允许卡顿但要保持清晰”的效果,可以设置 minVideoBitrate 为 videoBitrate 的 60%; |
| | | * - 如果您追求“允许模糊但要保持流畅”的效果,可以设置 minVideoBitrate 为 200kbps; |
| | | * - 如果您将 videoBitrate 和 minVideoBitrate 设置为同一个值,等价于关闭 SDK 的自适应调节能力; |
| | | * - 默认值:0,此时最低码率由 SDK 根据分辨率情况,自动设置合适的数值。<br> |
| | | * 【特别说明】<br> |
| | | * - 当您把分辨率设置的比较高时,minVideoBitrate 不适合设置的太低,否则会出现画面模糊和大范围的马赛克宏块。 |
| | | * 比如把分辨率设置为 720p,把码率设置为 200kbps,那么编码出的画面将会出现大范围区域性马赛克。 |
| | | * @param {Boolean} enableAdjustRes - 【字段含义】是否允许调整分辨率<br> |
| | | * 【推荐取值】 <br> |
| | | * - 手机直播建议选择 NO。<br> |
| | | * - 视频通话模式,若更关注流畅性,建议选择 YES,此时若遇到带宽有限的弱网,SDK 会自动降低分辨率以保障更好的流畅度(仅针对 TRTCVideoStreamTypeBig 生效)。 |
| | | * - 默认值:NO。<br> |
| | | * 【特别说明】若有录制需求,选择 YES 时,请确保通话过程中,调整分辨率不会影响您的录制效果。<br> |
| | | */ |
| | | export class TRTCVideoEncParam { |
| | | constructor(videoResolution = TRTCVideoResolution.TRTCVideoResolution_640_360, resMode = TRTCVideoResolutionMode.TRTCVideoResolutionModePortrait, videoFps = 15, videoBitrate = 550, minVideoBitrate = 0, enableAdjustRes = false) { |
| | | this.videoResolution = videoResolution; |
| | | this.videoResolutionMode = resMode; |
| | | this.videoFps = videoFps; |
| | | this.videoBitrate = videoBitrate; |
| | | this.minVideoBitrate = minVideoBitrate; |
| | | this.enableAdjustRes = enableAdjustRes; |
| | | } |
| | | } |
| | | ; |
| | | /** |
| | | * 画面渲染参数<br> |
| | | * 您可以通过设置此参数来控制画面的旋转、填充、镜像模式 |
| | | * @param {TRTCVideoRotation} rotation - 【字段含义】视频画面旋转方向 |
| | | * @param {TRTCVideoFillMode} fillMode - 【字段含义】视频画面填充模式 |
| | | * @param {TRTCVideoMirrorType} mirrorType - 【字段含义】画面渲染镜像类型 |
| | | */ |
| | | export class TRTCRenderParams { |
| | | constructor(rotation = TRTCVideoRotation.TRTCVideoRotation_0, fillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fit, mirrorType = TRTCVideoMirrorType.TRTCVideoMirrorType_Disable) { |
| | | this.rotation = rotation; |
| | | this.fillMode = fillMode; |
| | | this.mirrorType = mirrorType; |
| | | } |
| | | } |
| | | /** |
| | | * 屏幕分享参数(仅适用于 Android 平台)<br> |
| | | * 该设置决定了远端用户看到的画面质量(同时也是云端录制出的视频文件的画面质量)。 |
| | | * @param {Boolean} enableForegroundService - 是否同时启用 SDK 内置的前台服务,停止屏幕分享时会停止该服务。 |
| | | * 从 Android 10 开始,如果 APP 的 targetSdkVersion 大于等于 29 时, |
| | | * 需要有 mediaProjection 类型的前台服务才能成功开始,否则会报 SecurityException。您可以自己启动一个前台服务,也可以使用 SDK 内置的前台服务。当使用内置的前台服务时 ** 您需要在 manifest.json 中添加以下内容:<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />** |
| | | * @param {String} appGroup 默认值为空,仅开启应用内屏幕分享;如需开启应用外屏幕分享,请填写 appGroup,同时在插件中配置相关信息,详见[功能接入/ios部分](https://cloud.tencent.com/document/product/647/113834) |
| | | */ |
| | | export class TRTCScreenShareParams { |
| | | constructor(enableForegroundService, appGroup) { |
| | | this.enableForegroundService = enableForegroundService; |
| | | this.appGroup = appGroup; |
| | | } |
| | | } |
| | | ; |
| | | /** |
| | | * 音频路由(即声音的播放模式)<br> |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCAudioRoute_HACK_JSDOC = { |
| | | /** 使用扬声器播放(即“免提”),扬声器位于手机底部,声音偏大,适合外放音乐 */ |
| | | TRTCAudioRouteSpeaker: 0, |
| | | /** 使用听筒播放,听筒位于手机顶部,声音偏小,适合需要保护隐私的通话场景 */ |
| | | TRTCAudioRouteEarpiece: 1, |
| | | }; |
| | | export var TRTCAudioRoute; |
| | | (function (TRTCAudioRoute) { |
| | | TRTCAudioRoute[TRTCAudioRoute["TRTCAudioRouteSpeaker"] = 0] = "TRTCAudioRouteSpeaker"; |
| | | TRTCAudioRoute[TRTCAudioRoute["TRTCAudioRouteEarpiece"] = 1] = "TRTCAudioRouteEarpiece"; |
| | | })(TRTCAudioRoute || (TRTCAudioRoute = {})); |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【其它参数】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | export var TRTCShareSource; |
| | | (function (TRTCShareSource) { |
| | | TRTCShareSource["InApp"] = "InApp"; |
| | | TRTCShareSource["ByReplaykit"] = "ByReplaykit"; |
| | | })(TRTCShareSource || (TRTCShareSource = {})); |
| | | /** |
| | | * 重力感应开关(仅适用于移动端)<br> |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCGSensorMode_HACK_JSDOC = { |
| | | /** 不适配重力感应,该模式是桌面平台上的默认值,该模式下,当前用户发布出去的视频画面不受重力感应方向变化的影响。 */ |
| | | TRTC_GSENSOR_MODE_DISABLE: 0, |
| | | /** 适配重力感应,该模式是移动平台上的默认值,该模式下,当前用户发布出去的视频画面会跟随设备的重力感应方向进行相应的调整,同时本地预览画面保持方向不变。 |
| | | SDK 目前支持的一种适配模式是:当手机或 Pad 上下颠倒时,为了保证远端用户看到的画面方向正常,SDK 会自动将发布出去的画面上下旋转180度。如果您的 APP 的界面层开启了重力感应自适应,推荐使用 UIFixLayout 模式。 |
| | | */ |
| | | TRTC_GSENSOR_MODE_UIAUTOLAYOUT: 1, |
| | | }; |
| | | export var TRTCGSensorMode; |
| | | (function (TRTCGSensorMode) { |
| | | TRTCGSensorMode[TRTCGSensorMode["TRTC_GSENSOR_MODE_DISABLE"] = 0] = "TRTC_GSENSOR_MODE_DISABLE"; |
| | | TRTCGSensorMode[TRTCGSensorMode["TRTC_GSENSOR_MODE_UIAUTOLAYOUT"] = 1] = "TRTC_GSENSOR_MODE_UIAUTOLAYOUT"; |
| | | })(TRTCGSensorMode || (TRTCGSensorMode = {})); |
| | | /** |
| | | * 系统音量类型(仅适用于移动端)<br> |
| | | * - 通话音量:手机专门为接打电话所设计的音量类型,自带回声抵消(AEC)功能,并且支持通过蓝牙耳机上的麦克风进行拾音,缺点是音质比较一般。当您通过手机侧面的音量按键下调手机音量时,如果无法将其调至零(也就是无法彻底静音),说明您的手机当前处于通话音量。 |
| | | * - 媒体音量:手机专门为音乐场景所设计的音量类型,无法使用系统的 AEC 功能,并且不支持通过蓝牙耳机的麦克风进行拾音,但具备更好的音乐播放效果。当您通过手机侧面的音量按键下调手机音量时,如果能够将手机音量调至彻底静音,说明您的手机当前处于媒体音量。 |
| | | * @enum {Number} |
| | | */ |
| | | const TXSystemVolumeType_HACK_JSDOC = { |
| | | /** |
| | | * 自动切换模式: |
| | | * 也被称为“麦上通话,麦下媒体”,即主播上麦时使用通话音量,观众不上麦则使用媒体音量,适合在线直播场景。 |
| | | * 如果您在 enterRoom 时选择的场景为 TRTCAppSceneLIVE 或 TRTCAppSceneVoiceChatRoom,SDK 会自动使用该模式。 |
| | | */ |
| | | TXSystemVolumeTypeAuto: 0, |
| | | /** |
| | | * 全程媒体音量: |
| | | * 通话全程使用媒体音量,并不是非常常用的音量类型,适用于对音质要求比较苛刻的音乐场景中。 |
| | | * 如果您的用户大都使用外接设备(比如外接声卡)为主,可以使用该模式,否则请慎用。 |
| | | */ |
| | | TXSystemVolumeTypeMedia: 1, |
| | | /** |
| | | * 全程通话音量: |
| | | * 该方案的优势在于用户在上下麦时音频模块无需切换工作模式,可以做到无缝上下麦,适合于用户需要频繁上下麦的应用场景。 |
| | | * 如果您在 enterRoom 时选择的场景为 TRTCAppSceneVideoCall 或 TRTCAppSceneAudioCall,SDK 会自动使用该模式。 |
| | | */ |
| | | TXSystemVolumeTypeVOIP: 2, |
| | | }; |
| | | export var TXSystemVolumeType; |
| | | (function (TXSystemVolumeType) { |
| | | TXSystemVolumeType[TXSystemVolumeType["TXSystemVolumeTypeAuto"] = 0] = "TXSystemVolumeTypeAuto"; |
| | | TXSystemVolumeType[TXSystemVolumeType["TXSystemVolumeTypeMedia"] = 1] = "TXSystemVolumeTypeMedia"; |
| | | TXSystemVolumeType[TXSystemVolumeType["TXSystemVolumeTypeVOIP"] = 2] = "TXSystemVolumeTypeVOIP"; |
| | | })(TXSystemVolumeType || (TXSystemVolumeType = {})); |
| New file |
| | |
| | | export const NAME = { |
| | | ANDROID: 'android', |
| | | IOS: 'ios', |
| | | STRING: 'string', |
| | | FUNCTION: 'function', |
| | | BOOLEAN: 'boolean', |
| | | NUMBER: 'number', |
| | | LOG_PREFIX: '【UniApp-JS】', |
| | | }; |
| | | export const errorCodeUrl = 'https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/ErrorCode.html'; |
| New file |
| | |
| | | import TrtcCloudImpl from './TrtcCloudImpl.js'; |
| | | import { TRTCVideoStreamType } from './TrtcDefines.js'; |
| | | const version = '1.4.5'; |
| | | export * from './TrtcDefines.js'; |
| | | /** |
| | | * TrtcCloud |
| | | * |
| | | * @class TrtcCloud |
| | | */ |
| | | export default class TrtcCloud { |
| | | /** |
| | | * 创建 TrtcCloud 单例 |
| | | * |
| | | * @static |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * TrtcCloud.createInstance(); |
| | | */ |
| | | static createInstance() { |
| | | console.log('----------------------------------------------------------------'); |
| | | console.log(` SDK ${version} `); |
| | | console.log('----------------------------------------------------------------'); |
| | | return TrtcCloudImpl._createInstance(); |
| | | } |
| | | /** |
| | | * 销毁 TrtcCloud 单例 |
| | | * |
| | | * @static |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * TrtcCloud.destroyInstance(); |
| | | */ |
| | | static destroyInstance() { |
| | | return TrtcCloudImpl._destroyInstance(); |
| | | } |
| | | /** |
| | | * 设置 TrtcCloud 事件监听 |
| | | * |
| | | * @param {String} event 事件名称 |
| | | * @param {Function} callback 事件回调 |
| | | * @memberof TrtcCloud |
| | | * |
| | | * @example |
| | | * this.trtcCloud = TrtcCloud.createInstance(); // 创建 trtcCloud 实例 |
| | | * this.trtcCloud.on('onEnterRoom', (res) => {}); |
| | | */ |
| | | on(event, callback) { |
| | | return TrtcCloudImpl._getInstance().on(event, callback); |
| | | } |
| | | /** |
| | | * 取消事件绑定<br> |
| | | * |
| | | * @param {String} event 事件名称,传入通配符 '*' 会解除所有事件绑定。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.off('onEnterRoom'); |
| | | * |
| | | * this.trtcCloud.off('*'); // 取消所有绑定的事件 |
| | | */ |
| | | off(event) { |
| | | return TrtcCloudImpl._getInstance().off(event); |
| | | } |
| | | /** |
| | | * 进房<br> |
| | | * 调用接口后,您会收到来自 TRTCCallback 中的 [onEnterRoom(result)]{@link TRTCCallback#onEnterRoom} 回调 |
| | | * 如果加入成功,result 会是一个正数(result > 0),表示加入房间所消耗的时间,单位是毫秒(ms)。<br> |
| | | * 如果加入失败,result 会是一个负数(result < 0),表示进房失败的错误码。 |
| | | * |
| | | * * 参数 scene 的枚举值如下: |
| | | * - {@link TRTCAppSceneVideoCall}:<br> |
| | | * 视频通话场景,支持720P、1080P高清画质,单个房间最多支持300人同时在线,最高支持50人同时发言。<br> |
| | | * 适合:[1对1视频通话]、[300人视频会议]、[在线问诊]、[视频聊天]、[远程面试]等。<br> |
| | | * - {@link TRTCAppSceneAudioCall}:<br> |
| | | * 语音通话场景,支持 48kHz,支持双声道。单个房间最多支持300人同时在线,最高支持50人同时发言。<br> |
| | | * 适合:[1对1语音通话]、[300人语音会议]、[语音聊天]、[语音会议]、[在线狼人杀]等。<br> |
| | | * - {@link TRTCAppSceneLIVE}:<br> |
| | | * 视频互动直播,支持平滑上下麦,切换过程无需等待,主播延时小于300ms;支持十万级别观众同时播放,播放延时低至1000ms。<br> |
| | | * 适合:[视频低延时直播]、[十万人互动课堂]、[视频直播 PK]、[视频相亲房]、[互动课堂]、[远程培训]、[超大型会议]等。<br> |
| | | * - {@link TRTCAppSceneVoiceChatRoom}:<br> |
| | | * 语音互动直播,支持平滑上下麦,切换过程无需等待,主播延时小于300ms;支持十万级别观众同时播放,播放延时低至1000ms。<br> |
| | | * 适合:[语音低延时直播]、[语音直播连麦]、[语聊房]、[K 歌房]、[FM 电台]等。<br> |
| | | * |
| | | * **Note:** |
| | | * 1. 当 scene 选择为 TRTCAppSceneLIVE 或 TRTCAppSceneVoiceChatRoom 时,您必须通过 TRTCParams 中的 role 字段指定当前用户的角色。 |
| | | * 2. 不管进房是否成功,enterRoom 都必须与 exitRoom 配对使用,在调用 `exitRoom` 前再次调用 `enterRoom` 函数会导致不可预期的错误问题。 |
| | | * |
| | | * @param {TRTCParams} params - 进房参数 |
| | | * @param {Number} params.sdkAppId - 应用标识(必填) |
| | | * @param {String} params.userId - 用户标识(必填) |
| | | * @param {String} params.userSig - 用户签名(必填) |
| | | * @param {Number} params.roomId - 房间号码, roomId 和 strRoomId 必须填一个, 若您选用 strRoomId,则 roomId 需要填写为0。 |
| | | * @param {String} params.strRoomId - 字符串房间号码 [选填],在同一个房间内的用户可以看到彼此并进行视频通话, roomId 和 strRoomId 必须填一个。若两者都填,则优先选择 roomId |
| | | * @param {TRTCRoleType} params.role - 直播场景下的角色,默认值:主播 |
| | | * - TRTCRoleAnchor: 主播,可以上行视频和音频,一个房间里最多支持50个主播同时上行音视频。 |
| | | * - TRTCRoleAudience: 观众,只能观看,不能上行视频和音频,一个房间里的观众人数没有上限。 |
| | | * @param {String=} params.privateMapKey - 房间签名(非必填) |
| | | * @param {String=} params.businessInfo - 业务数据(非必填) |
| | | * @param {String=} params.streamId - 自定义 CDN 播放地址(非必填) |
| | | * @param {String=} params.userDefineRecordId - 设置云端录制完成后的回调消息中的 "userdefinerecordid" 字段内容,便于您更方便的识别录制回调(非必填) |
| | | * @param {TRTCAppScene} scene 应用场景,目前支持视频通话(TRTCAppSceneVideoCall)、语音通话(TRTCAppSceneAudioCall)、在线直播(TRTCAppSceneLIVE)、语音聊天室(VTRTCAppSceneVoiceChatRoom)四种场景, |
| | | * 详见 [TrtcDefines] 中 TRTCAppScene 参数定义 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCAppScene } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud = TrtcCloud.createInstance(); // 创建实例,只需创建一次 |
| | | * const params = { |
| | | * sdkAppId: 0, |
| | | * userId: 'xxx', |
| | | * roomId: 12345, |
| | | * userSig: 'xxx' |
| | | * }; |
| | | * this.trtcCloud.enterRoom(params, TRTCAppScene.TRTCAppSceneVideoCall); |
| | | */ |
| | | enterRoom(params, scene) { |
| | | return TrtcCloudImpl._getInstance().enterRoom(params, scene); |
| | | } |
| | | /** |
| | | * 退房<br> |
| | | * 执行退出房间的相关逻辑释放资源后,SDK 会通过 `onExitRoom()` 回调通知到您 |
| | | * |
| | | * **Note:** |
| | | * 1. 如果您要再次调用 `enterRoom()` 或者切换到其它的音视频 SDK,请等待 `onExitRoom()` 回调到来后再执行相关操作,否则可能会遇到如摄像头、麦克风设备被强占等各种异常问题。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.exitRoom(); |
| | | */ |
| | | exitRoom() { |
| | | return TrtcCloudImpl._getInstance().exitRoom(); |
| | | } |
| | | /** |
| | | * 切换角色,仅适用于直播场景(TRTCAppSceneLIVE 和 TRTCAppSceneVoiceChatRoom) |
| | | * |
| | | * 在直播场景下,一个用户可能需要在“观众”和“主播”之间来回切换。 |
| | | * 您可以在进房前通过 TRTCParams 中的 role 字段确定角色,也可以通过 switchRole 在进房后切换角色。 |
| | | * |
| | | * @param {TRTCRoleType} role - 目标角色,默认为主播 |
| | | * - TRTCRoleAnchor: 主播,可以上行视频和音频,一个房间里最多支持50个主播同时上行音视频。 |
| | | * - TRTCRoleAudience: 观众,只能观看,不能上行视频和音频,一个房间里的观众人数没有上限。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCRoleType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.switchRole(TRTCRoleType.TRTCRoleAudience); |
| | | */ |
| | | switchRole(role) { |
| | | return TrtcCloudImpl._getInstance().switchRole(role); |
| | | } |
| | | /** |
| | | * 请求跨房通话 |
| | | * |
| | | * 默认情况下,只有同一个房间中的用户之间可以进行音视频通话,不同的房间之间的音视频流是相互隔离的。 |
| | | * 使用该接口让身处两个不同房间中的主播进行跨房间的音视频流分享,从而让每个房间中的观众都能观看到这两个主播的音视频。 |
| | | * 跨房通话的请求结果会通过监听 [onConnectOtherRoom](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TRTCCallback.html#event:onConnectOtherRoom) 事件通知给您。 |
| | | * |
| | | * @param {Object} params - 跨房通话参数 |
| | | * - 如果对端的房间号为数字,那么传入的参数为 roomId。 |
| | | * - 如果对端的房间号为字符串,那么传入的参数为 strRoomId。 |
| | | * - 针对对端的房间号类型传递对应参数,不需要两个同时传递。具体请看 example 的使用。 |
| | | * @param {Number} params.roomId 跨房通话时对端的数字房间号 roomId(与 strRoomId 选填其中一个,不可同时传递) |
| | | * @param {String} params.strRoomId 跨房通话时对端的字符串房间号 strRoomId(与 roomId 选填其中一个,不可同时传递) |
| | | * @param {String} params.userId 跨房通话时对端的 userId(必填) |
| | | * |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.connectOtherRoom({"roomId": 1233, "userId": "user_11"}); |
| | | * this.trtcCloud.connectOtherRoom({"strRoomId": "1233", "userId": "user_22"}); |
| | | */ |
| | | connectOtherRoom(params) { |
| | | return TrtcCloudImpl._getInstance().connectOtherRoom(params); |
| | | } |
| | | /** |
| | | * 退出跨房通话 |
| | | * |
| | | * 退出跨房通话的请求结果会通过监听 [onDisconnectOtherRoom](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TRTCCallback.html#event:onDisconnectOtherRoom) 事件通知给您。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.disconnectOtherRoom(); |
| | | */ |
| | | disconnectOtherRoom() { |
| | | return TrtcCloudImpl._getInstance().disconnectOtherRoom(); |
| | | } |
| | | /** |
| | | * 开启本地视频的预览画面<br> |
| | | * 当开始渲染首帧摄像头画面时,您会收到 `onFirstVideoFrame(null)` 回调 |
| | | * |
| | | * @param {Boolean} isFrontCamera 前置、后置摄像头,true:前置摄像头;false:后置摄像头,**默认为 true** |
| | | * @param {String=} viewId 用于承载视频画面的渲染控件,使用原生插件中的 TRTCCloudUniPlugin-TXLocalViewComponent component,需要提供 viewId 属性值,例如 viewId=userId |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * // 预览本地画面 |
| | | * const viewId = this.userId; |
| | | * this.trtcCloud.startLocalPreview(true, viewId); |
| | | */ |
| | | startLocalPreview(isFrontCamera = true, viewId) { |
| | | return TrtcCloudImpl._getInstance().startLocalPreview(isFrontCamera, viewId); |
| | | } |
| | | /** |
| | | * 设置视频编码器的编码参数 |
| | | * - 该设置能够决定远端用户看到的画面质量,同时也能决定云端录制出的视频文件的画面质量。 |
| | | * @param {TRTCVideoEncParam} param 用于设置视频编码器的相关参数 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * |
| | | * import { TRTCVideoResolution, TRTCVideoResolutionMode, TRTCVideoEncParam } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const videoResolution = TRTCVideoResolution.TRTCVideoResolution_480_360; |
| | | * const videoResolutionMode = TRTCVideoResolutionMode.TRTCVideoResolutionModeLandscape; // 横屏采集 |
| | | * const videoFps = 15; |
| | | * const videoBitrate = 900; |
| | | * const minVideoBitrate = 200; |
| | | * const enableAdjustRes = false; |
| | | * // const param = new TRTCVideoEncParam(videoResolution, videoResolutionMode, videoFps, videoBitrate, minVideoBitrate, enableAdjustRes); // v1.1.0 方式 |
| | | * |
| | | * const param = { // v1.2.0 以上版本支持的方式 |
| | | * videoResolution, |
| | | * videoResolutionMode, |
| | | * videoFps, |
| | | * videoBitrate, |
| | | * minVideoBitrate, |
| | | * enableAdjustRes, |
| | | * }; |
| | | * |
| | | * this.trtcCloud.setVideoEncoderParam(param); |
| | | */ |
| | | setVideoEncoderParam(param) { |
| | | return TrtcCloudImpl._getInstance().setVideoEncoderParam(param); |
| | | } |
| | | /** |
| | | * 切换前置或后置摄像头 |
| | | * |
| | | * @param {Boolean} isFrontCamera 前置、后置摄像头,true:前置摄像头;false:后置摄像头 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * // 切换前置或后置摄像头 |
| | | * const isFrontCamera = true; |
| | | * this.trtcCloud.switchCamera(isFrontCamera); |
| | | */ |
| | | switchCamera(isFrontCamera) { |
| | | return TrtcCloudImpl._getInstance().switchCamera(isFrontCamera); |
| | | } |
| | | /** |
| | | * 停止本地视频采集及预览 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.stopLocalPreview(); |
| | | */ |
| | | stopLocalPreview() { |
| | | return TrtcCloudImpl._getInstance().stopLocalPreview(); |
| | | } |
| | | /** |
| | | * 设置本地画面的渲染参数,可设置的参数包括有:画面的旋转角度、填充模式以及左右镜像等。 |
| | | * @param {TRTCRenderParams} params - 本地图像的参数 |
| | | * @param {TRTCVideoRotation} params.rotation - 图像的顺时针旋转角度,支持90、180以及270旋转角度,默认值:TRTCVideoRotation.TRTCVideoRotation_0 |
| | | * @param {TRTCVideoFillMode} params.fillMode - 视频画面填充模式,填充(画面可能会被拉伸裁剪)或适应(画面可能会有黑边),默认值:TRTCVideoFillMode.TRTCVideoFillMode_Fill |
| | | * @param {TRTCVideoMirrorType} params.mirrorType - 画面镜像模式,默认值:TRTCVideoMirrorType.TRTCVideoMirrorType_Auto |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoRotation, TRTCVideoFillMode, TRTCVideoMirrorType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const renderParams = { |
| | | * rotation: TRTCVideoRotation.TRTCVideoRotation_0, |
| | | * fillMode: TRTCVideoFillMode.TRTCVideoFillMode_Fill, |
| | | * mirrorType: TRTCVideoMirrorType.TRTCVideoMirrorType_Auto |
| | | * }; |
| | | * this.trtcCloud.setLocalRenderParams(renderParams); |
| | | */ |
| | | setLocalRenderParams(params) { |
| | | return TrtcCloudImpl._getInstance().setLocalRenderParams(params); |
| | | } |
| | | /** |
| | | * 暂停/恢复发布本地的视频流 |
| | | * |
| | | * 该接口可以暂停(或恢复)发布本地的视频画面,暂停之后,同一房间中的其他用户将无法继续看到自己画面。 该接口在指定 TRTCVideoStreamTypeBig 时等效于 start/stopLocalPreview 这两个接口,但具有更好的响应速度。 因为 start/stopLocalPreview 需要打开和关闭摄像头,而打开和关闭摄像头都是硬件设备相关的操作,非常耗时。 相比之下,muteLocalVideo 只需要在软件层面对数据流进行暂停或者放行即可,因此效率更高,也更适合需要频繁打开关闭的场景。 当暂停/恢复发布指定 TRTCVideoStreamTypeBig 后,同一房间中的其他用户将会收到 onUserVideoAvailable 回调通知。 当暂停/恢复发布指定 TRTCVideoStreamTypeSub 后,同一房间中的其他用户将会收到 onUserSubStreamAvailable 回调通知。 |
| | | * @param {Number} streamType 要暂停/恢复的视频流类型(仅支持 TRTCVideoStreamTypeBig 和 TRTCVideoStreamTypeSub) |
| | | * @param {Boolean} mute - true:屏蔽;false:开启,默认值:false |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.muteLocalVideo(TRTCVideoStreamType.TRTCVideoStreamTypeBig, true); |
| | | */ |
| | | muteLocalVideo(streamType, mute) { |
| | | return TrtcCloudImpl._getInstance().muteLocalVideo(streamType, mute); |
| | | } |
| | | /** |
| | | * 显示远端视频或辅流<br> |
| | | * |
| | | * @param {String} userId 指定远端用户的 userId |
| | | * @param {Number} streamType 指定要观看 userId 的视频流类型 |
| | | * - 高清大画面:TRTCVideoStreamType.TRTCVideoStreamTypeBig |
| | | * - 低清小画面:TRTCVideoStreamType.TRTCVideoStreamTypeSmall |
| | | * - 辅流(屏幕分享):TRTCVideoStreamType.TRTCVideoStreamTypeSub |
| | | * @param {String} viewId 用于承载视频画面的渲染控件,使用原生插件中的 TRTCCloudUniPlugin-TXRemoteViewComponent component,需要提供 viewId 属性值,例如 viewId=userId |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoStreamType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const viewId = this.remoteUserId; |
| | | * this.trtcCloud.startRemoteView(userId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, viewId); |
| | | */ |
| | | startRemoteView(userId, streamType, viewId) { |
| | | return TrtcCloudImpl._getInstance().startRemoteView(userId, streamType, viewId); |
| | | } |
| | | /** |
| | | * 停止显示远端视频画面,同时不再拉取该远端用户的视频数据流<br> |
| | | * 指定要停止观看的 userId 的视频流类型 |
| | | * |
| | | * @param {String} userId 指定的远端用户 ID |
| | | * @param {Number} streamType |
| | | * - 高清大画面:TRTCVideoStreamType.TRTCVideoStreamTypeBig |
| | | * - 低清小画面:TRTCVideoStreamType.TRTCVideoStreamTypeSmall |
| | | * - 辅流(屏幕分享):TRTCVideoStreamType.TRTCVideoStreamTypeSub |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoStreamType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.stopRemoteView(remoteUserId, TRTCVideoStreamType.TRTCVideoStreamTypeBig); |
| | | */ |
| | | stopRemoteView(userId, streamType) { |
| | | return TrtcCloudImpl._getInstance().stopRemoteView(userId, streamType); |
| | | } |
| | | /** |
| | | * 设置远端画面的渲染参数,可设置的参数包括有:画面的旋转角度、填充模式以及左右镜像等。 |
| | | * @param {String} userId 远端用户 ID |
| | | * @param {Number} streamType 可以设置为主路画面(TRTCVideoStreamTypeBig)或辅路画面(TRTCVideoStreamTypeSub) |
| | | * @param {TRTCRenderParams} params - 图像的参数 |
| | | * @param {TRTCVideoRotation} params.rotation - 图像的顺时针旋转角度,支持90、180以及270旋转角度,默认值:TRTCVideoRotation.TRTCVideoRotation_0 |
| | | * @param {TRTCVideoFillMode} params.fillMode - 视频画面填充模式,填充(画面可能会被拉伸裁剪)或适应(画面可能会有黑边),默认值:TRTCVideoFillMode.TRTCVideoFillMode_Fill |
| | | * @param {TRTCVideoMirrorType} params.mirrorType - 画面镜像模式,默认值:TRTCVideoMirrorType.TRTCVideoMirrorType_Auto |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoRotation, TRTCVideoFillMode, TRTCVideoMirrorType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const renderParams = { |
| | | * rotation: TRTCVideoRotation.TRTCVideoRotation_0, |
| | | * fillMode: TRTCVideoFillMode.TRTCVideoFillMode_Fill, |
| | | * mirrorType: TRTCVideoMirrorType.TRTCVideoMirrorType_Auto |
| | | * }; |
| | | * this.trtcCloud.setRemoteRenderParams(userId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, renderParams); |
| | | */ |
| | | setRemoteRenderParams(userId, streamType, params) { } |
| | | /** |
| | | * 设置视频编码器输出的画面方向<br> |
| | | * 该设置不影响本地画面的预览方向,但会影响房间中其他用户所观看到(以及云端录制文件)的画面方向。 |
| | | * 当用户将手机或 Pad 上下颠倒时,由于摄像头的采集方向没有变,所以房间中其他用户所看到的画面会变成上下颠倒的, |
| | | * 在这种情况下,您可以通过调用该接口将 SDK 编码出的画面方向旋转180度,如此一来,房间中其他用户所看到的画面可保持正常的方向。 |
| | | * 如果您希望实现上述这种友好的交互体验,我们更推荐您直接调用 setGSensorMode 实现更加智能的方向适配,无需您手动调用本接口。 |
| | | * @param {Number} rotation 目前支持 0、90、180、270 两个旋转角度,默认值:TRTCVideoRotation_0,即不旋转。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoRotation } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.setVideoEncoderRotation(TRTCVideoRotation.TRTCVideoRotation_90); |
| | | */ |
| | | setVideoEncoderRotation(rotation) { |
| | | return TrtcCloudImpl._getInstance().setVideoEncoderRotation(rotation); |
| | | } |
| | | /** |
| | | * 设置编码器输出的画面镜像模式 |
| | | * @param {Boolean} mirror 是否开启远端镜像,true:开启远端画面镜像;false:关闭远端画面镜像,默认值:false。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.setVideoEncoderMirror(true); |
| | | */ |
| | | setVideoEncoderMirror(mirror) { |
| | | return TrtcCloudImpl._getInstance().setVideoEncoderMirror(mirror); |
| | | } |
| | | /** |
| | | * 设置重力感应的适配模式<br> |
| | | * 您可以通过本接口实现如下这种友好的交互体验: |
| | | * 当用户将手机或 Pad 上下颠倒时,由于摄像头的采集方向没有变,所以房间中其他用户所看到的画面会变成上下颠倒的, |
| | | * 在这种情况下,您可以通过调用该接口让 SDK 根据设备陀螺仪的朝向自动调整本地画面和编码器输出画面的旋转方向,以使远端观众可以看到正常朝向的画面。 |
| | | * @param {Number} mode 重力感应模式,详情请参见 TRTCGSensorMode,默认值:TRTCGSensorMode_UIAutoLayout。。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCGSensorMode } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.setGSensorMode(TRTCGSensorMode.TRTC_GSENSOR_MODE_DISABLE); |
| | | */ |
| | | setGSensorMode(mode) { |
| | | return TrtcCloudImpl._getInstance().setGSensorMode(mode); |
| | | } |
| | | /** |
| | | * 视频画面截图 |
| | | * |
| | | * 您可以通过本接口截取本地的视频画面,远端用户的主路画面以及远端用户的辅路(屏幕分享)画面。 |
| | | * |
| | | * @param {String | null} userId 用户 ID,如指定 null 表示截取本地的视频画面 |
| | | * @param {Number} streamType 视频流类型,可选择截取主路画面(TRTCVideoStreamTypeBig,常用于摄像头)或辅路画面(TRTCVideoStreamTypeSub,常用于屏幕分享) |
| | | * @param {TRTCSnapshotSourceType} sourceType 画面来源,可选择截取视频流画面(TRTCSnapshotSourceTypeStream)或视频渲染画面(TRTCSnapshotSourceTypeView),前者一般更清晰 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoStreamType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.snapshotVideo(null, TRTCVideoStreamType.TRTCVideoStreamTypeBig, TRTCSnapshotSourceType.TRTCSnapshotSourceTypeStream); // 截取本地视频流画面 |
| | | * this.trtcCloud.snapshotVideo(this.remoteUserId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, TRTCSnapshotSourceType.TRTCSnapshotSourceTypeView); // 截取远端指定用户视频渲染画面 |
| | | */ |
| | | snapshotVideo(userId, streamType, sourceType) { |
| | | return TrtcCloudImpl._getInstance().snapshotVideo(userId, streamType, sourceType); |
| | | } |
| | | /** |
| | | * 开启本地音频的采集和上行, 并设置音频质量<br> |
| | | * 该函数会启动麦克风采集,并将音频数据传输给房间里的其他用户。 SDK 不会默认开启本地音频采集和上行,您需要调用该函数开启,否则房间里的其他用户将无法听到您的声音<br> |
| | | * 主播端的音质越高,观众端的听感越好,但传输所依赖的带宽也就越高,在带宽有限的场景下也更容易出现卡顿 |
| | | * |
| | | * @param {TRTCAudioQuality} quality 声音音质 |
| | | * - TRTCAudioQualitySpeech,流畅:采样率:16k;单声道;音频裸码率:16kbps;适合语音通话为主的场景,比如在线会议,语音通话。 |
| | | * - TRTCAudioQualityDefault,默认:采样率:48k;单声道;音频裸码率:50kbps;SDK 默认的音频质量,如无特殊需求推荐选择之。 |
| | | * - TRTCAudioQualityMusic,高音质:采样率:48k;双声道 + 全频带;音频裸码率:128kbps;适合需要高保真传输音乐的场景,比如在线K歌、音乐直播等 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCAudioQuality } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.startLocalAudio(TRTCAudioQuality.TRTCAudioQualityDefault); |
| | | */ |
| | | startLocalAudio(quality) { |
| | | return TrtcCloudImpl._getInstance().startLocalAudio(quality); |
| | | } |
| | | /** |
| | | * 关闭本地音频的采集和上行<br> |
| | | * 当关闭本地音频的采集和上行,房间里的其它成员会收到 `onUserAudioAvailable(false)` 回调通知 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.stopLocalAudio(); |
| | | */ |
| | | stopLocalAudio() { |
| | | return TrtcCloudImpl._getInstance().stopLocalAudio(); |
| | | } |
| | | /** |
| | | * 静音本地的音频 |
| | | * |
| | | * 当静音本地音频后,房间里的其它成员会收到 onUserAudioAvailable(false) 回调通知。 |
| | | * 与 stopLocalAudio 不同之处在于,muteLocalAudio 并不会停止发送音视频数据,而是会继续发送码率极低的静音包。 |
| | | * 在对录制质量要求很高的场景中,选择 muteLocalAudio 是更好的选择,能录制出兼容性更好的 MP4 文件。 |
| | | * 这是由于 MP4 等视频文件格式,对于音频的连续性是要求很高的,简单粗暴地 stopLocalAudio 会导致录制出的 MP4 不易播放。 |
| | | * |
| | | * @param {Boolean} mute - true:屏蔽;false:开启,默认值:false |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.muteLocalAudio(true); |
| | | */ |
| | | muteLocalAudio(mute) { |
| | | return TrtcCloudImpl._getInstance().muteLocalAudio(mute); |
| | | } |
| | | /** |
| | | * 静音掉某一个用户的声音,同时不再拉取该远端用户的音频数据流 |
| | | * |
| | | * @param {String} userId - 用户 ID |
| | | * @param {Boolean} mute - true:静音;false:非静音 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.muteRemoteAudio('denny', true); |
| | | */ |
| | | muteRemoteAudio(userId, mute) { |
| | | return TrtcCloudImpl._getInstance().muteRemoteAudio(userId, mute); |
| | | } |
| | | /** |
| | | * 静音掉所有用户的声音,同时不再拉取该远端用户的音频数据流 |
| | | * |
| | | * @param {Boolean} mute - true:静音;false:非静音 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.muteAllRemoteAudio(true); |
| | | */ |
| | | muteAllRemoteAudio(mute) { |
| | | return TrtcCloudImpl._getInstance().muteAllRemoteAudio(mute); |
| | | } |
| | | /** |
| | | * 设置音频路由 |
| | | * |
| | | * 设置“音频路由”,即设置声音是从手机的扬声器还是从听筒中播放出来,因此该接口仅适用于手机等移动端设备。 手机有两个扬声器:一个是位于手机顶部的听筒,一个是位于手机底部的立体声扬声器。 |
| | | * 设置音频路由为听筒时,声音比较小,只有将耳朵凑近才能听清楚,隐私性较好,适合用于接听电话。 设置音频路由为扬声器时,声音比较大,不用将手机贴脸也能听清,因此可以实现“免提”的功能。 |
| | | * |
| | | * @param {TRTCAudioRoute} route 音频路由,即声音由哪里输出(扬声器、听筒), 默认值:TRTCAudioRoute.TRTCAudioRouteSpeaker(扬声器), |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCAudioRoute } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.setAudioRoute(TRTCAudioRoute.TRTCAudioRouteSpeaker); // TRTCAudioRoute.TRTCAudioRouteEarpiece (听筒) |
| | | */ |
| | | setAudioRoute(route) { |
| | | return TrtcCloudImpl._getInstance().setAudioRoute(route); |
| | | } |
| | | /** |
| | | * 启用或关闭音量大小提示 |
| | | * |
| | | * 开启此功能后,SDK 会在 onUserVoiceVolume() 中反馈对每一路声音音量大小值的评估。 |
| | | * |
| | | * **Note:** |
| | | * - 如需打开此功能,请在 startLocalAudio 之前调用才可以生效。 |
| | | * |
| | | * @param {Number} interval - 设置 onUserVoiceVolume 回调的触发间隔,单位为ms,最小间隔为100ms,如果小于等于0则会关闭回调,建议设置为300ms |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.enableAudioVolumeEvaluation(300); |
| | | */ |
| | | enableAudioVolumeEvaluation(interval) { |
| | | return TrtcCloudImpl._getInstance().enableAudioVolumeEvaluation(interval); |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 屏幕分享 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 设置屏幕分享(即辅路)的视频编码参数 |
| | | * |
| | | * 该接口可以设定远端用户所看到的屏幕分享(即辅路)的画面质量,同时也能决定云端录制出的视频文件中屏幕分享的画面质量。 请注意如下两个接口的差异: |
| | | * - setVideoEncoderParam 用于设置主路画面(TRTCVideoStreamTypeBig,一般用于摄像头)的视频编码参数。 |
| | | * - setSubStreamEncoderParam 用于设置辅路画面(TRTCVideoStreamTypeSub,一般用于屏幕分享)的视频编码参数。 |
| | | * |
| | | * **Note:** |
| | | * - 即使您使用主路传输屏幕分享(在调用 startScreenCapture 时设置 type=TRTCVideoStreamTypeBig),依然要使用 setSubStreamEncoderParam 设定屏幕分享的编码参数,而不要使用 setVideoEncoderParam |
| | | * @param {TRTCVideoEncParam} param 辅流编码参数,详情请参考 TRTCVideoEncParam。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const params = { |
| | | * videoResolution: TRTCVideoResolution.TRTCVideoResolution_640_360, |
| | | * videoResolutionMode: TRTCVideoResolutionMode.TRTCVideoResolutionModePortrait, |
| | | * videoFps: 15, |
| | | * videoBitrate: 900, |
| | | * minVideoBitrate: 200, |
| | | * enableAdjustRes: false, |
| | | * }; |
| | | * this.trtcCloud.setSubStreamEncoderParam(params); |
| | | */ |
| | | setSubStreamEncoderParam(param) { |
| | | return TrtcCloudImpl._getInstance().setSubStreamEncoderParam(param); |
| | | } |
| | | /** |
| | | * 启动屏幕分享 |
| | | * |
| | | * **Note:** |
| | | * - 一个用户同时最多只能上传一条主路(TRTCVideoStreamTypeBig)画面和一条辅路(TRTCVideoStreamTypeSub)画面, |
| | | * 默认情况下,屏幕分享使用辅路画面,如果使用主路画面,建议您提前停止摄像头采集(stopLocalPreview)避免相互冲突。 |
| | | * - **仅支持 iOS 13.0 及以上系统,进行应用内的屏幕分享;若要应用外屏幕分享,需填写 shareParams.appGroup 字段。** |
| | | * - **Android: UniApp 使用 SDK 内置的前台服务时,只需要将接口参数 enableForegroundService 设置为 true。** |
| | | * - **Android: UniApp 自己启动前台,需要在 mediaProject 类型的前台服务成功后再启动屏幕分享。** |
| | | * |
| | | * @param {Number} streamType 屏幕分享使用的线路,可以设置为主路(TRTCVideoStreamTypeBig)或者辅路(TRTCVideoStreamTypeSub),推荐使用 |
| | | * @param {TRTCVideoEncParam} encParams 屏幕分享的画面编码参数,可以设置为 null,表示让 SDK 选择最佳的编码参数(分辨率、码率等)。即使在调用 startScreenCapture 时设置 type=TRTCVideoStreamTypeBig,依然可以使用此接口更新屏幕分享的编码参数。 |
| | | * @param {TRTCScreenShareParams} shareParams 您可以通过其中的 enableForegroundService 参数启用 SDK 内置的前台服务; 当 appGroup 正确填写时,会开启 iOS 系统屏幕分享;如果不填写 appGroup, 则默认使用应用内屏幕分享。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoResolution, TRTCVideoResolutionMode, TRTCVideoStreamType} from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const encParams = { |
| | | * videoResolution: TRTCVideoResolution.TRTCVideoResolution_640_360, |
| | | * videoResolutionMode: TRTCVideoResolutionMode.TRTCVideoResolutionModePortrait, |
| | | * videoFps: 15, |
| | | * videoBitrate: 900, |
| | | * minVideoBitrate: 200, |
| | | * enableAdjustRes: false, |
| | | * }; |
| | | * const shareParams = { |
| | | * enableForegroundService: true, |
| | | * appGroup: 'xxx', |
| | | * }; |
| | | * this.trtcCloud.startScreenCapture(TRTCVideoStreamType.TRTCVideoStreamTypeSub, encParams, shareParams); |
| | | */ |
| | | startScreenCapture(streamType = TRTCVideoStreamType.TRTCVideoStreamTypeSub, encParams = null, shareParams = {}) { |
| | | return TrtcCloudImpl._getInstance().startScreenCapture(streamType, encParams, shareParams); |
| | | } |
| | | /** |
| | | * 停止屏幕分享 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.stopScreenCapture(); |
| | | */ |
| | | stopScreenCapture() { |
| | | return TrtcCloudImpl._getInstance().stopScreenCapture(); |
| | | } |
| | | /** |
| | | * 暂停屏幕分享 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.pauseScreenCapture(); |
| | | */ |
| | | pauseScreenCapture() { |
| | | return TrtcCloudImpl._getInstance().pauseScreenCapture(); |
| | | } |
| | | /** |
| | | * 恢复屏幕分享 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.resumeScreenCapture(); |
| | | */ |
| | | resumeScreenCapture() { |
| | | return TrtcCloudImpl._getInstance().resumeScreenCapture(); |
| | | } |
| | | /** |
| | | * 设置系统音量类型(仅适用于移动设备) |
| | | * |
| | | * @param {TXSystemVolumeType} type 系统音量类型 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.setSystemVolumeType(TXSystemVolumeType.TXSystemVolumeTypeAuto) |
| | | */ |
| | | setSystemVolumeType(type) { |
| | | return TrtcCloudImpl._getInstance().setSystemVolumeType(type); |
| | | } |
| | | /** |
| | | * 设置本地画面被暂停期间的替代图片 |
| | | * |
| | | * 当您调用 muteLocaLVideo(true)暂停本地画面时,您可以通过调用本接口设置一张替代图片,设置后,房间中的其他用户会看到这张替代图片,而不是黑屏画面。 |
| | | * |
| | | * @param {Number} fps 设置替代图片帧率,最小值为5,最大值为10,默认5。 |
| | | * @param {String} image 设置替代图片,空值代表在 muteLocalVideo 之后不再发送视频流数据,默认值为空。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.setVideoMuteImage(6, 'xxxx'); |
| | | */ |
| | | setVideoMuteImage(fps, image) { |
| | | return TrtcCloudImpl._getInstance().setVideoMuteImage(fps, image); |
| | | } |
| | | /** |
| | | * 开启大小画面双路编码模式 |
| | | * |
| | | * 开启双路编码模式后,当前用户的编码器会同时输出【高清大画面】和【低清小画面】两路视频流(但只有一路音频流)。 |
| | | * 如此以来,房间中的其他用户就可以根据自身的网络情况或屏幕大小选择订阅【高清大画面】或是【低清小画面】。 |
| | | |
| | | * @param {Boolean} enable 是否开启小画面编码,默认值:false。 |
| | | * @param {TRTCVideoEncParam} smallVideoEncParam 小流的视频参数。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoEncParam, TRTCVideoResolution, TRTCVideoResolutionMode } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.enableEncSmallVideoStream(true, {videoResolution: TRTCVideoResolution.TRTCVideoResolution_120_120, videoResolutionMode: TRTCVideoResolutionMode.TRTCVideoResolutionModeLandscape}) |
| | | */ |
| | | enableEncSmallVideoStream(enable, smallVideoEncParam) { |
| | | return TrtcCloudImpl._getInstance().enableEncSmallVideoStream(enable, smallVideoEncParam); |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 美颜 + 水印 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 设置美颜(磨皮)算法 |
| | | * TRTC 内置多种不同的磨皮算法,您可以选择最适合您产品定位的方案 |
| | | * |
| | | * **Note:** |
| | | * - 设置美颜前,先调用 `setBeautyLevel` 设置美颜级别。否则美颜级别为 0 表示关闭美颜 |
| | | * |
| | | * @param {TRTCBeautyStyle} beautyStyle 美颜风格,TRTCBeautyStyleSmooth:光滑;TRTCBeautyStyleNature:自然;TRTCBeautyStylePitu:优图 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCBeautyStyle } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const beautyLevel = 5; // 美颜级别,取值范围0 - 9; 0表示关闭,9表示效果最明显。 |
| | | * this.trtcCloud.setBeautyLevel(beautyLevel); |
| | | * this.trtcCloud.setBeautyStyle(TRTCBeautyStyle.TRTCBeautyStyleSmooth); |
| | | */ |
| | | setBeautyStyle(beautyStyle) { |
| | | return TrtcCloudImpl._getInstance().setBeautyStyle(beautyStyle); |
| | | } |
| | | /** |
| | | * 设置美颜级别 |
| | | * @param {Number} beautyLevel 美颜级别,取值范围0 - 9; 0表示关闭,9表示效果最明显。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const beautyLevel = 5; // 美颜级别,取值范围0 - 9; 0表示关闭,9表示效果最明显。 |
| | | * this.trtcCloud.setBeautyLevel(beautyLevel); |
| | | */ |
| | | setBeautyLevel(beautyLevel) { |
| | | return TrtcCloudImpl._getInstance().setBeautyLevel(beautyLevel); |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 背景音效 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 开始播放背景音乐 |
| | | * 每个音乐都需要您指定具体的 ID,您可以通过该 ID 对音乐的开始、停止、音量等进行设置。<br> |
| | | * **Note:** |
| | | * - 如果要多次播放同一首背景音乐,请不要每次播放都分配一个新的 ID,我们推荐使用相同的 ID。 |
| | | * - 若您希望同时播放多首不同的音乐,请为不同的音乐分配不同的 ID 进行播放。 |
| | | * - 如果使用同一个 ID 播放不同音乐,SDK 会先停止播放旧的音乐,再播放新的音乐。 |
| | | * |
| | | * **Note:**<br> |
| | | * 在 uni-app 中 path 如何获取。 |
| | | * - 使用 cdn 地址,例如:`path = https://web.sdk.qcloud.com/component/TUIKit/assets/uni-app/calling-bell-1.mp3;` |
| | | * - 使用本地绝对路径。 |
| | | * 1. 通过 [uni.saveFile](https://zh.uniapp.dcloud.io/api/file/file.html#savefile) 获取保存后的相对路径(建议这种路径)。 |
| | | * 2. 将上一步的相对路径转成绝对路径,[plus.io.convertLocalFileSystemURL](https://www.html5plus.org/doc/zh_cn/io.html#plus.io.convertLocalFileSystemURL)。 |
| | | * |
| | | * @param {AudioMusicParam} musicParam 音乐参数 |
| | | * @param {Number} musicParam.id 音乐 ID |
| | | * @param {String} musicParam.path 音效文件的完整路径或 URL 地址。支持的音频格式包括 MP3、AAC、M4A、WAV |
| | | * @param {Number} musicParam.loopCount 音乐循环播放的次数。取值范围为0 - 任意正整数,默认值:0。0表示播放音乐一次;1表示播放音乐两次;以此类推 |
| | | * @param {Boolean} musicParam.publish 是否将音乐传到远端。true:音乐在本地播放的同时,远端用户也能听到该音乐;false:主播只能在本地听到该音乐,远端观众听不到。默认值:false。 |
| | | * @param {Boolean} musicParam.isShortFile 播放的是否为短音乐文件。true:需要重复播放的短音乐文件;false:正常的音乐文件。默认值:false |
| | | * @param {Number} musicParam.startTimeMS 音乐开始播放时间点,单位: 毫秒。 |
| | | * @param {Number} musicParam.endTimeMS 音乐结束播放时间点,单位: 毫秒,0 表示播放至文件结尾。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { AudioMusicParam } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const musicParam = { |
| | | * id: 1, |
| | | * path: '', |
| | | * loopCount: 1, |
| | | * publish: true, |
| | | * isShortFile: false, |
| | | * startTimeMS: 0, |
| | | * endTimeMS: 0, |
| | | * }; |
| | | * this.trtcCloud.startPlayMusic(musicParam); |
| | | */ |
| | | startPlayMusic(musicParam) { |
| | | return TrtcCloudImpl._getInstance().startPlayMusic(musicParam); |
| | | } |
| | | /** |
| | | * 停止播放背景音乐 |
| | | * @param {Number} id 音乐 ID |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const musicId = 5; |
| | | * this.trtcCloud.stopPlayMusic(musicId); |
| | | */ |
| | | stopPlayMusic(id) { |
| | | return TrtcCloudImpl._getInstance().stopPlayMusic(id); |
| | | } |
| | | /** |
| | | * 暂停播放背景音乐 |
| | | * @param {Number} id 音乐 ID |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const musicId = 5; |
| | | * this.trtcCloud.pausePlayMusic(musicId); |
| | | */ |
| | | pausePlayMusic(id) { |
| | | return TrtcCloudImpl._getInstance().pausePlayMusic(id); |
| | | } |
| | | /** |
| | | * 恢复播放背景音乐 |
| | | * @param {Number} id 音乐 ID |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const musicId = 5; |
| | | * this.trtcCloud.resumePlayMusic(musicId); |
| | | */ |
| | | resumePlayMusic(id) { |
| | | return TrtcCloudImpl._getInstance().resumePlayMusic(id); |
| | | } |
| | | /** |
| | | * 调用实验性接口 |
| | | * @param {any} params 实验性接口参数 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.callExperimentalAPI(params); |
| | | */ |
| | | callExperimentalAPI(params) { |
| | | return TrtcCloudImpl._getInstance().callExperimentalAPI(params); |
| | | } |
| | | /** |
| | | * 使用 UDP 通道发送自定义消息给房间内所有用户<br> |
| | | * 该接口可以让您借助 TRTC 的 UDP 通道,向当前房间里的其他用户广播自定义数据,以达到传输信令的目的。 |
| | | * 房间中的其他用户可以通过 onRecvCustomCmdMsg 事件接收消息。 |
| | | * |
| | | * **Note:** |
| | | * 1. 发送消息到房间内所有用户(暂时不支持 Web/小程序端),每秒最多能发送30条消息(与 {sendSEIMsg} 共享限制)。 |
| | | * 2. 每个包最大为 1KB,超过则很有可能会被中间路由器或者服务器丢弃。 |
| | | * 3. 每个客户端每秒最多能发送总计 16KB 数据(与 {sendSEIMsg} 共享限制)。 |
| | | * 4. 请将 `reliable` 和 `ordered` 同时设置为 true 或同时设置为 false,暂不支持交叉设置。 |
| | | * 5. 强烈建议您将不同类型的消息设定为不同的 cmdID,这样可以在要求有序的情况下减小消息时延。 |
| | | * |
| | | * @param {any} params - 参数 |
| | | * @param {Number} params.cmdID - 消息 ID,取值范围为 [1, 10] |
| | | * @param {String} params.data - 待发送的消息,单个消息的最大长度被限制为 1KB |
| | | * @param {Boolean} params.reliable - 是否可靠发送,可靠发送可以获得更高的发送成功率,但可靠发送比不可靠发送会带来更大的接收延迟 |
| | | * @param {Number} params.ordered - 是否要求有序,即是否要求接收端的数据包顺序和发送端的数据包顺序一致(这会带来一定的接收延时) |
| | | * @return true:消息已经发出;false:消息发送失败。 |
| | | |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const params = { |
| | | * cmdID: 1, |
| | | * data: 'hello world', |
| | | * reliable: true, |
| | | * ordered: true, |
| | | * }; |
| | | * this.trtcCloud.sendCustomCmdMsg(params); |
| | | */ |
| | | sendCustomCmdMsg(params) { |
| | | return TrtcCloudImpl._getInstance().sendCustomCmdMsg(params); |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 设置 TRTCCallback 回调 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 设置 TrtcCloud 回调 |
| | | * |
| | | * @example |
| | | * // 创建/使用/销毁 TrtcCloud 对象的示例代码: |
| | | * import TrtcCloud from '@/TrtcCloud/lib/index'; |
| | | * this.trtcCloud = new TrtcCloud(); |
| | | * |
| | | * // 添加事件监听的方法,事件关键字详见下方”通用事件回调“ |
| | | * this.trtcCloud.on('onEnterRoom', (result) => { |
| | | * if (result > 0) { |
| | | * console.log(`enter room success, spend ${result}ms`); |
| | | * } else { |
| | | * console.log(`enter room failed, error code = ${result}`); |
| | | * } |
| | | * }); |
| | | * |
| | | * @namespace TRTCCallback |
| | | */ |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // (一)事件回调 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 错误回调,表示 SDK 不可恢复的错误,一定要监听并分情况给用户适当的界面提示<br> |
| | | * @event TRTCCallback#onError |
| | | * @param {Number} code 错误码,[详见](https://cloud.tencent.com/document/product/647/38308#.E9.94.99.E8.AF.AF.E7.A0.81.E8.A1.A8) |
| | | * @param {String} message 错误信息 |
| | | * @param {Object} extraInfo 扩展信息字段,个别错误码可能会带额外的信息帮助定位问题 |
| | | */ |
| | | onError(code, message, extraInfo) { } |
| | | /** |
| | | * 警告回调,用于告知您一些非严重性问题,例如出现卡顿或者可恢复的解码失败<br> |
| | | * @event TRTCCallback#onWarning |
| | | * @param {Number} code 警告码,[详见](https://cloud.tencent.com/document/product/647/38308#.E8.AD.A6.E5.91.8A.E7.A0.81.E8.A1.A8) |
| | | * @param {String} message 警告信息 |
| | | * @param {Object} extraInfo 扩展信息字段,个别警告码可能会带额外的信息帮助定位问题 |
| | | */ |
| | | onWarning(code, message, extraInfo) { } |
| | | /** |
| | | * 进房后的回调<br> |
| | | * 调用 `enterRoom()` 接口执行进房操作后,会收到 `onEnterRoom(result)` 回调<br> |
| | | * 如果加入成功,result 会是一个正数(result > 0),代表加入房间的时间消耗,单位是毫秒(ms)。<br> |
| | | * 如果加入失败,result 会是一个负数(result < 0),代表进房失败的错误码。 |
| | | * |
| | | * @event TRTCCallback#onEnterRoom |
| | | * @param {Number} result 进房耗时 |
| | | */ |
| | | onEnterRoom(result) { } |
| | | /** |
| | | * 离开房间的事件回调<br> |
| | | * 调用 `exitRoom()` 接口会执行退出房间的相关逻辑,例如释放音视频设备资源和编解码器资源等。待资源释放完毕,会通过 `onExitRoom()` 回调通知到您<br> |
| | | * |
| | | * **Note:** |
| | | * - 如果您要再次调用 `enterRoom()` 或者切换到其他的音视频 SDK,请等待 `onExitRoom()` 回调到来之后再执行相关操作。 否则可能会遇到音频设备被占用等各种异常问题 |
| | | * |
| | | * @event TRTCCallback#onExitRoom |
| | | * @param {Number} reason 离开房间原因,0:主动调用 exitRoom 退房;1:被服务器踢出当前房间;2:当前房间整个被解散 |
| | | */ |
| | | onExitRoom(reason) { } |
| | | /** |
| | | * 跨房通话事件回调<br> |
| | | * 调用 TRTCCloud 中的 [connectOtherRoom()](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TrtcCloud.html#connectOtherRoom) 接口会将两个不同房间中的主播拉通视频通话,也就是所谓的“主播PK”功能。 |
| | | * 调用者会收到 onConnectOtherRoom() 事件回调来获知跨房通话是否成功, 如果成功,两个房间中的所有用户都会收到来自另一个房间中的 PK 主播的 [onUserVideoAvailable()](http://127.0.0.1:5500/UniApp-TRTC-SDK/packages/TrtcCloud/docs/zh-cn/api/TRTCCallback.html#event:onUserVideoAvailable) 回调。 |
| | | * |
| | | * @event TRTCCallback#onConnectOtherRoom |
| | | * @param {Object} params 调用 [connectOtherRoom()](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TrtcCloud.html#connectOtherRoom) 接口返回值数据。 |
| | | * - userId:跨房通话时对端 userId |
| | | * - errCode: [错误状态码](https://cloud.tencent.com/document/product/647/38308#.E8.AD.A6.E5.91.8A.E7.A0.81.E8.A1.A8),返回0表示跨房通话成功。 |
| | | * - errMsg: 状态信息,跨房通话成功返回 OK。 |
| | | */ |
| | | onConnectOtherRoom(params) { } |
| | | /** |
| | | * 结束跨房通话的结果回调<br> |
| | | * 调用 TRTCCloud 中的 [disconnectOtherRoom()](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TrtcCloud.html#disconnectOtherRoom) 接口会将两个不同房间中的主播拉通视频通话,也就是所谓的“主播PK”功能。 |
| | | * 调用者会收到 onDisconnectOtherRoom() 事件回调来获知结束跨房通话是否成功。 |
| | | * |
| | | * @event TRTCCallback#onDisconnectOtherRoom |
| | | * @param {Object} params 调用 [disconnectOtherRoom()](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TrtcCloud.html#disconnectOtherRoom) 失败时返回的错误数据。 |
| | | * - errCode: [错误状态码](https://cloud.tencent.com/document/product/647/38308#.E8.AD.A6.E5.91.8A.E7.A0.81.E8.A1.A8)。 |
| | | * - errMsg: 错误信息。 |
| | | */ |
| | | onDisconnectOtherRoom(params) { } |
| | | /** |
| | | * 切换角色的事件回调<br> |
| | | * 调用 TRTCCloud 中的 switchRole() 接口会切换主播和观众的角色,该操作会伴随一个线路切换的过程, 待 SDK 切换完成后,会抛出 onSwitchRole() 事件回调 |
| | | * |
| | | * @event TRTCCallback#onSwitchRole |
| | | * @param {Number} code 错误码,[详见](https://cloud.tencent.com/document/product/647/38308#.E8.AD.A6.E5.91.8A.E7.A0.81.E8.A1.A8) |
| | | * @param {String} message 错误信息 |
| | | */ |
| | | onSwitchRole(code, message) { } |
| | | /** |
| | | * 开始渲染本地或远程用户的首帧画面<br> |
| | | * 如果 userId 为 null,代表开始渲染本地采集的摄像头画面,需要您先调用 `startLocalPreview` 触发。 如果 userId 不为 null,代表开始渲染远程用户的首帧画面,需要您先调用 `startRemoteView` 触发<br> |
| | | * 只有当您调用 `startLocalPreview()、startRemoteView() 或 startRemoteSubStreamView()` 之后,才会触发该回调 |
| | | * |
| | | * @event TRTCCallback#onFirstVideoFrame |
| | | * @param {String} userId 本地或远程用户 ID,如果 userId === null 代表本地,userId !== null 代表远程 |
| | | * @param {Number} streamType 视频流类型:摄像头或屏幕分享 |
| | | * @param {Number} width 画面宽度 |
| | | * @param {Number} height 画面高度 |
| | | */ |
| | | onFirstVideoFrame(userId, streamType, width, height) { } |
| | | /** |
| | | * 开始播放远程用户的首帧音频(本地声音暂不通知)<br> |
| | | * 如果 userId 为 null,代表开始渲染本地采集的摄像头画面,需要您先调用 `startLocalPreview` 触发。 如果 userId 不为 null,代表开始渲染远程用户的首帧画面,需要您先调用 `startRemoteView` 触发<br> |
| | | * 只有当您调用 `startLocalPreview()、startRemoteView() 或 startRemoteSubStreamView()` 之后,才会触发该回调 |
| | | * |
| | | * @event TRTCCallback#onFirstAudioFrame |
| | | * @param {String} userId 远程用户 ID |
| | | */ |
| | | onFirstAudioFrame(userId) { } |
| | | /** |
| | | * 截图完成时回调<br> |
| | | * @event TRTCCallback#onSnapshotComplete |
| | | * @param {String} base64Data 截图对应的 base64 数据 |
| | | * @param {String} message 错误信息 |
| | | */ |
| | | onSnapshotComplete(base64Data, message) { } |
| | | /** |
| | | * 麦克风准备就绪 |
| | | */ |
| | | onMicDidReady() { } |
| | | /** |
| | | * 摄像头准备就绪 |
| | | */ |
| | | onCameraDidReady() { } |
| | | /** |
| | | * 网络质量:该回调每2秒触发一次,统计当前网络的上行和下行质量<br> |
| | | * userId 为本地用户 ID 代表自己当前的视频质量 |
| | | * |
| | | * @param {String} localQuality 上行网络质量 |
| | | * @param {String} remoteQuality 下行网络质量 |
| | | */ |
| | | onNetworkQuality(localQuality, remoteList) { } |
| | | /** |
| | | * 有用户加入当前房间<br> |
| | | * 出于性能方面的考虑,在两种不同的应用场景下,该通知的行为会有差别:<br> |
| | | * 通话场景(TRTCAppScene.TRTCAppSceneVideoCall 和 TRTCAppScene.TRTCAppSceneAudioCall):该场景下用户没有角色的区别,任何用户进入房间都会触发该通知。<br> |
| | | * 直播场景(TRTCAppScene.TRTCAppSceneLIVE 和 TRTCAppScene.TRTCAppSceneVoiceChatRoom ):该场景不限制观众的数量,如果任何用户进出都抛出回调会引起很大的性能损耗,所以该场景下只有主播进入房间时才会触发该通知,观众进入房间不会触发该通知 |
| | | * |
| | | * @event TRTCCallback#onRemoteUserEnterRoom |
| | | * @param {String} userId 用户标识 ID |
| | | */ |
| | | onRemoteUserEnterRoom(userId) { } |
| | | /** |
| | | * 有用户离开当前房间<br> |
| | | * 与 onRemoteUserEnterRoom 相对应,在两种不同的应用场景下,该通知的行为会有差别:<br> |
| | | * 通话场景(TRTCAppScene.TRTCAppSceneVideoCall 和 TRTCAppScene.TRTCAppSceneAudioCall):该场景下用户没有角色的区别,任何用户进入房间都会触发该通知。<br> |
| | | * 直播场景(TRTCAppScene.TRTCAppSceneLIVE 和 TRTCAppScene.TRTCAppSceneVoiceChatRoom ):该场景不限制观众的数量,如果任何用户进出都抛出回调会引起很大的性能损耗,所以该场景下只有主播进入房间时才会触发该通知,观众进入房间不会触发该通知 |
| | | * |
| | | * @event TRTCCallback#onRemoteUserLeaveRoom |
| | | * @param {String} userId 用户标识 ID |
| | | * @param {Number} reason 离开原因,0 表示用户主动退出房间,1 表示用户超时退出,2 表示被踢出房间 |
| | | */ |
| | | onRemoteUserLeaveRoom(userId, reason) { } |
| | | /** |
| | | * 首帧本地音频数据已经被送出<br> |
| | | * 在 `enterRoom()` 并 `startLocalAudio()` 成功后开始麦克风采集,并将采集到的声音进行编码。 当 SDK 成功向云端送出第一帧音频数据后,会抛出这个回调事件 |
| | | * |
| | | * @event TRTCCallback#onSendFirstLocalAudioFrame |
| | | */ |
| | | onSendFirstLocalAudioFrame() { } |
| | | /** |
| | | * 首帧本地视频数据已经被送出<br> |
| | | * SDK 会在 `enterRoom()` 并 `startLocalPreview()` 成功后开始摄像头采集,并将采集到的画面进行编码。 当 SDK 成功向云端送出第一帧视频数据后,会抛出这个回调事件 |
| | | * |
| | | * @event TRTCCallback#onSendFirstLocalVideoFrame |
| | | * @param {Number} streamType 视频流类型,大画面、小画面或辅流画面(屏幕分享) |
| | | */ |
| | | onSendFirstLocalVideoFrame(streamType) { } |
| | | /** |
| | | * 技术指标统计回调<br> |
| | | * 如果您是熟悉音视频领域相关术语,可以通过这个回调获取 SDK 的所有技术指标。 如果您是首次开发音视频相关项目,可以只关注 `onNetworkQuality` 回调 |
| | | * |
| | | * **Note:** |
| | | * - 每 2 秒回调一次 |
| | | * |
| | | * @param {Object} statics 状态数据 |
| | | */ |
| | | onStatistics(statics) { } |
| | | /** |
| | | * 远端用户是否存在可播放的音频数据<br> |
| | | * @event TRTCCallback#onUserAudioAvailable |
| | | * @param {String} userId 用户标识 ID |
| | | * @param {Boolean} available 声音是否开启 |
| | | */ |
| | | onUserAudioAvailable(userId, available) { } |
| | | /** |
| | | * 远端用户是否存在可播放的主路画面(一般用于摄像头)<br> |
| | | * 当您收到 `onUserVideoAvailable(userId, true)` 通知时,表示该路画面已经有可用的视频数据帧到达。 此时,您需要调用 `startRemoteView(userId)` 接口加载该用户的远程画面。 然后,您会收到名为 onFirstVideoFrame(userid) 的首帧画面渲染回调。<br> |
| | | * 当您收到 `onUserVideoAvailable(userId, false)` 通知时,表示该路远程画面已经被关闭,可能由于该用户调用了 `muteLocalVideo()` 或 `stopLocalPreview()`。 |
| | | * |
| | | * @event TRTCCallback#onUserVideoAvailable |
| | | * @param {String} userId 用户标识 ID |
| | | * @param {Boolean} available 画面是否开启 |
| | | */ |
| | | onUserVideoAvailable(userId, available) { } |
| | | /** |
| | | * 用于提示音量大小的回调,包括每个 userId 的音量和远端总音量<br> |
| | | * SDK 可以评估每一路音频的音量大小,并每隔一段时间抛出该事件回调,您可以根据音量大小在 UI 上做出相应的提示,比如“波形图”或“音量槽”。 要完成这个功能, 您需要先调用 enableAudioVolumeEvaluation 开启这个能力并设定事件抛出的时间间隔。 需要补充说明的是,无论当前房间中是否有人说话,SDK 都会按照您设定的时间间隔定时抛出此事件回调,只不过当没有人说话时,userVolumes 为空,totalVolume 为 0。 |
| | | * |
| | | * **Note:** |
| | | * - userVolumes 为一个数组,对于数组中的每一个元素,当 userId 为空时表示本地麦克风采集的音量大小,当 userId 不为空时代表远端用户的音量大小 |
| | | * |
| | | * @event TRTCCallback#onUserVoiceVolume |
| | | * @param {Array} userVolumes 是一个数组,用于承载所有正在说话的用户的音量大小,取值范围 0 - 100 |
| | | * @param {Number} totalVolume 所有远端用户的总音量大小, 取值范围 0 - 100 |
| | | */ |
| | | onUserVoiceVolume(userVolumes, totalVolume) { } |
| | | /** |
| | | * 屏幕分享开启的事件回调<br> |
| | | * 当您通过 startScreenCapture 等相关接口启动屏幕分享时,SDK 便会抛出此事件回调 |
| | | * @event TRTCCallback#onScreenCaptureStarted |
| | | */ |
| | | onScreenCaptureStarted() { } |
| | | /** |
| | | * 屏幕分享停止的事件回调<br> |
| | | * 当您通过 stopScreenCapture 停止屏幕分享时,SDK 便会抛出此事件回调 |
| | | * @event TRTCCallback#onScreenCaptureStopped |
| | | * @param {Number} reason 停止原因,0:用户主动停止;1:屏幕窗口关闭导致停止;2:表示屏幕分享的显示屏状态变更(如接口被拔出、投影模式变更等) |
| | | */ |
| | | onScreenCaptureStopped(reason) { } |
| | | /** |
| | | * 屏幕分享停止的事件回调<br> |
| | | * 当您通过 pauseScreenCapture 停止屏幕分享时,SDK 便会抛出此事件回调 |
| | | * @event TRTCCallback#onScreenCapturePaused |
| | | * @param {Number} reason 停止原因,0:用户主动停止;1:屏幕窗口关闭导致停止;2:表示屏幕分享的显示屏状态变更(如接口被拔出、投影模式变更等) |
| | | */ |
| | | onScreenCapturePaused(reason) { } |
| | | /** |
| | | * 屏幕分享恢复的事件回调<br> |
| | | * 当您通过 resumeScreenCapture 恢复屏幕分享时,SDK 便会抛出此事件回调 |
| | | * @event TRTCCallback#onScreenCaptureResumed |
| | | */ |
| | | onScreenCaptureResumed() { } |
| | | /** |
| | | * 某远端用户发布/取消了辅路视频画面<br> |
| | | * “辅路画面”一般被用于承载屏幕分享的画面。当您收到 onUserSubStreamAvailable(userId, true) 通知时,表示该路画面已经有可播放的视频帧到达。 此时,您需要调用 startRemoteView 接口订阅该用户的远程画面,订阅成功后,您会继续收到该用户的首帧画面渲染回调 onFirstVideoFrame(userId) |
| | | * |
| | | * **Note:** |
| | | * - 拉取 Web 端(用 [WebRTC](https://web.sdk.qcloud.com/trtc/webrtc/doc/zh-cn/index.html) 实现屏幕分享)的屏幕分享,收不到 onUserSubStreamAvailable 事件。因为 [WebRTC](https://web.sdk.qcloud.com/trtc/webrtc/doc/zh-cn/index.html) 推的屏幕分享也是主流 |
| | | * @param {String} userId 用户 ID |
| | | * @param {Boolean} available 是否可用,true 表示辅流可用 |
| | | * @event TRTCCallback#onUserSubStreamAvailable |
| | | */ |
| | | onUserSubStreamAvailable(userId, available) { } |
| | | /** |
| | | * 用户视频大小发生改变回调。<br> |
| | | * 当您收到 onUserVideoSizeChanged(userId, streamtype, newWidth, newHeight) 通知时,表示该路画面大小发生了调整,调整的原因可能是该用户调用了 setVideoEncoderParam 或者 setSubStreamEncoderParam 重新设置了画面尺寸。 |
| | | * @param {String} userId 用户 ID |
| | | * @param {Number} streamType 视频流类型,仅支持 TRTCVideoStreamTypeBig 和 TRTCVideoStreamTypeSub |
| | | * @param {Number} newWidth 视频流的宽度(像素) |
| | | * @param {Number} newHeight 视频流的高度(像素) |
| | | * @event TRTCCallback#onUserVideoSizeChanged |
| | | */ |
| | | onUserVideoSizeChanged(userId, streamType, newWidth, newHeight) { } |
| | | /** |
| | | * 背景音乐开始播放 |
| | | * @param {Number} id 播放的 id |
| | | * @param {Number} errCode 播放的状态码 |
| | | * @event TRTCCallback#onStart |
| | | */ |
| | | onStart(id, errCode) { } |
| | | /** |
| | | * 背景音乐的播放进度 |
| | | * @param {Number} id 播放的 id |
| | | * @param {Number} curPtsMS 当前播放的位置 |
| | | * @param {Number} durationMS 当前音频总时长 |
| | | * @event TRTCCallback#onPlayProgress |
| | | */ |
| | | onPlayProgress(id, curPtsMS, durationMS) { } |
| | | /** |
| | | * 背景音乐已经播放完毕 |
| | | * @param {Number} id 播放的 id |
| | | * @param {Number} errCode 播放结束的状态码 |
| | | * @event TRTCCallback#onComplete |
| | | */ |
| | | onComplete(id, errCode) { } |
| | | /** |
| | | * 收到自定义消息的事件回调。 |
| | | * |
| | | * 当房间中的某个用户使用 {sendCustomCmdMsg} 发送自定义 UDP 消息时,房间中的其他用户可以通过 `onRecvCustomCmdMsg` 事件回调接收到该条消息。 |
| | | * @param {String} userId 用户标识。 |
| | | * @param {Number} cmdID 命令 ID。 |
| | | * @param {Number} seq 消息序号。 |
| | | * @param {String} message 消息数据。 |
| | | * @event TRTCCallback#onRecvCustomCmdMsg |
| | | */ |
| | | onRecvCustomCmdMsg(userId, cmdID, seq, message) { } |
| | | } |
| New file |
| | |
| | | /** |
| | | * 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启 |
| | | */ |
| | | var isIos |
| | | // #ifdef APP-PLUS |
| | | isIos = (plus.os.name == "iOS"); |
| | | // #endif |
| | | |
| | | // 判断推送权限是否开启 |
| | | function judgeIosPermissionPush() { |
| | | var result = false; |
| | | var UIApplication = plus.ios.import("UIApplication"); |
| | | var app = UIApplication.sharedApplication(); |
| | | var enabledTypes = 0; |
| | | if (app.currentUserNotificationSettings) { |
| | | var settings = app.currentUserNotificationSettings(); |
| | | enabledTypes = settings.plusGetAttribute("types"); |
| | | console.log("enabledTypes1:" + enabledTypes); |
| | | if (enabledTypes == 0) { |
| | | console.log("推送权限没有开启"); |
| | | } else { |
| | | result = true; |
| | | console.log("已经开启推送功能!") |
| | | } |
| | | plus.ios.deleteObject(settings); |
| | | } else { |
| | | enabledTypes = app.enabledRemoteNotificationTypes(); |
| | | if (enabledTypes == 0) { |
| | | console.log("推送权限没有开启!"); |
| | | } else { |
| | | result = true; |
| | | console.log("已经开启推送功能!") |
| | | } |
| | | console.log("enabledTypes2:" + enabledTypes); |
| | | } |
| | | plus.ios.deleteObject(app); |
| | | plus.ios.deleteObject(UIApplication); |
| | | return result; |
| | | } |
| | | |
| | | // 判断定位权限是否开启 |
| | | function judgeIosPermissionLocation() { |
| | | var result = false; |
| | | var cllocationManger = plus.ios.import("CLLocationManager"); |
| | | var status = cllocationManger.authorizationStatus(); |
| | | result = (status != 2) |
| | | console.log("定位权限开启:" + result); |
| | | // 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation |
| | | /* var enable = cllocationManger.locationServicesEnabled(); |
| | | var status = cllocationManger.authorizationStatus(); |
| | | console.log("enable:" + enable); |
| | | console.log("status:" + status); |
| | | if (enable && status != 2) { |
| | | result = true; |
| | | console.log("手机定位服务已开启且已授予定位权限"); |
| | | } else { |
| | | console.log("手机系统的定位没有打开或未给予定位权限"); |
| | | } */ |
| | | plus.ios.deleteObject(cllocationManger); |
| | | return result; |
| | | } |
| | | // 判断麦克风权限是否开启 |
| | | function judgeIosPermissionRecord() { |
| | | var result = false; |
| | | var avaudiosession = plus.ios.import("AVAudioSession"); |
| | | var avaudio = avaudiosession.sharedInstance(); |
| | | var permissionStatus = avaudio.recordPermission(); |
| | | console.log("permissionStatus:" + permissionStatus); |
| | | if (permissionStatus == 1684369017 || permissionStatus == 1970168948) { |
| | | console.log("麦克风权限没有开启"); |
| | | } else { |
| | | result = true; |
| | | console.log("麦克风权限已经开启"); |
| | | } |
| | | plus.ios.deleteObject(avaudiosession); |
| | | return result; |
| | | } |
| | | |
| | | // 判断相机权限是否开启 |
| | | function judgeIosPermissionCamera() { |
| | | var result = false; |
| | | var AVCaptureDevice = plus.ios.import("AVCaptureDevice"); |
| | | var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide'); |
| | | console.log("authStatus:" + authStatus); |
| | | if (authStatus == 3) { |
| | | result = true; |
| | | console.log("相机权限已经开启"); |
| | | } else { |
| | | console.log("相机权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(AVCaptureDevice); |
| | | return result; |
| | | } |
| | | |
| | | // 判断相册权限是否开启 |
| | | function judgeIosPermissionPhotoLibrary() { |
| | | var result = false; |
| | | var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary"); |
| | | var authStatus = PHPhotoLibrary.authorizationStatus(); |
| | | console.log("authStatus:" + authStatus); |
| | | if (authStatus == 3) { |
| | | result = true; |
| | | console.log("相册权限已经开启"); |
| | | } else { |
| | | console.log("相册权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(PHPhotoLibrary); |
| | | return result; |
| | | } |
| | | |
| | | // 判断通讯录权限是否开启 |
| | | function judgeIosPermissionContact() { |
| | | var result = false; |
| | | var CNContactStore = plus.ios.import("CNContactStore"); |
| | | var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0); |
| | | if (cnAuthStatus == 3) { |
| | | result = true; |
| | | console.log("通讯录权限已经开启"); |
| | | } else { |
| | | console.log("通讯录权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(CNContactStore); |
| | | return result; |
| | | } |
| | | |
| | | // 判断日历权限是否开启 |
| | | function judgeIosPermissionCalendar() { |
| | | var result = false; |
| | | var EKEventStore = plus.ios.import("EKEventStore"); |
| | | var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0); |
| | | if (ekAuthStatus == 3) { |
| | | result = true; |
| | | console.log("日历权限已经开启"); |
| | | } else { |
| | | console.log("日历权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(EKEventStore); |
| | | return result; |
| | | } |
| | | |
| | | // 判断备忘录权限是否开启 |
| | | function judgeIosPermissionMemo() { |
| | | var result = false; |
| | | var EKEventStore = plus.ios.import("EKEventStore"); |
| | | var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1); |
| | | if (ekAuthStatus == 3) { |
| | | result = true; |
| | | console.log("备忘录权限已经开启"); |
| | | } else { |
| | | console.log("备忘录权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(EKEventStore); |
| | | return result; |
| | | } |
| | | |
| | | // Android权限查询 |
| | | function requestAndroidPermission(permissionID) { |
| | | return new Promise((resolve, reject) => { |
| | | plus.android.requestPermissions( |
| | | [permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装 |
| | | function(resultObj) { |
| | | var result = 0; |
| | | for (var i = 0; i < resultObj.granted.length; i++) { |
| | | var grantedPermission = resultObj.granted[i]; |
| | | console.log('已获取的权限:' + grantedPermission); |
| | | result = 1 |
| | | } |
| | | for (var i = 0; i < resultObj.deniedPresent.length; i++) { |
| | | var deniedPresentPermission = resultObj.deniedPresent[i]; |
| | | console.log('拒绝本次申请的权限:' + deniedPresentPermission); |
| | | result = 0 |
| | | } |
| | | for (var i = 0; i < resultObj.deniedAlways.length; i++) { |
| | | var deniedAlwaysPermission = resultObj.deniedAlways[i]; |
| | | console.log('永久拒绝申请的权限:' + deniedAlwaysPermission); |
| | | result = -1 |
| | | } |
| | | resolve(result); |
| | | // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限 |
| | | // if (result != 1) { |
| | | // gotoAppPermissionSetting() |
| | | // } |
| | | }, |
| | | function(error) { |
| | | console.log('申请权限错误:' + error.code + " = " + error.message); |
| | | resolve({ |
| | | code: error.code, |
| | | message: error.message |
| | | }); |
| | | } |
| | | ); |
| | | }); |
| | | } |
| | | |
| | | // 使用一个方法,根据参数判断权限 |
| | | function judgeIosPermission(permissionID) { |
| | | if (permissionID == "location") { |
| | | return judgeIosPermissionLocation() |
| | | } else if (permissionID == "camera") { |
| | | return judgeIosPermissionCamera() |
| | | } else if (permissionID == "photoLibrary") { |
| | | return judgeIosPermissionPhotoLibrary() |
| | | } else if (permissionID == "record") { |
| | | return judgeIosPermissionRecord() |
| | | } else if (permissionID == "push") { |
| | | return judgeIosPermissionPush() |
| | | } else if (permissionID == "contact") { |
| | | return judgeIosPermissionContact() |
| | | } else if (permissionID == "calendar") { |
| | | return judgeIosPermissionCalendar() |
| | | } else if (permissionID == "memo") { |
| | | return judgeIosPermissionMemo() |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // 跳转到**应用**的权限页面 |
| | | function gotoAppPermissionSetting() { |
| | | if (isIos) { |
| | | var UIApplication = plus.ios.import("UIApplication"); |
| | | var application2 = UIApplication.sharedApplication(); |
| | | var NSURL2 = plus.ios.import("NSURL"); |
| | | // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES"); |
| | | var setting2 = NSURL2.URLWithString("app-settings:"); |
| | | application2.openURL(setting2); |
| | | |
| | | plus.ios.deleteObject(setting2); |
| | | plus.ios.deleteObject(NSURL2); |
| | | plus.ios.deleteObject(application2); |
| | | } else { |
| | | // console.log(plus.device.vendor); |
| | | var Intent = plus.android.importClass("android.content.Intent"); |
| | | var Settings = plus.android.importClass("android.provider.Settings"); |
| | | var Uri = plus.android.importClass("android.net.Uri"); |
| | | var mainActivity = plus.android.runtimeMainActivity(); |
| | | var intent = new Intent(); |
| | | intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); |
| | | var uri = Uri.fromParts("package", mainActivity.getPackageName(), null); |
| | | intent.setData(uri); |
| | | mainActivity.startActivity(intent); |
| | | } |
| | | } |
| | | |
| | | // 检查系统的设备服务是否开启 |
| | | // var checkSystemEnableLocation = async function () { |
| | | function checkSystemEnableLocation() { |
| | | if (isIos) { |
| | | var result = false; |
| | | var cllocationManger = plus.ios.import("CLLocationManager"); |
| | | var result = cllocationManger.locationServicesEnabled(); |
| | | console.log("系统定位开启:" + result); |
| | | plus.ios.deleteObject(cllocationManger); |
| | | return result; |
| | | } else { |
| | | var context = plus.android.importClass("android.content.Context"); |
| | | var locationManager = plus.android.importClass("android.location.LocationManager"); |
| | | var main = plus.android.runtimeMainActivity(); |
| | | var mainSvr = main.getSystemService(context.LOCATION_SERVICE); |
| | | var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER); |
| | | console.log("系统定位开启:" + result); |
| | | return result |
| | | } |
| | | } |
| | | |
| | | // module.exports = { |
| | | // judgeIosPermission: judgeIosPermission, |
| | | // requestAndroidPermission: requestAndroidPermission, |
| | | // checkSystemEnableLocation: checkSystemEnableLocation, |
| | | // gotoAppPermissionSetting: gotoAppPermissionSetting |
| | | // } |
| | | |
| | | // HBuilder 选择 vue3 时, 上面的打包无法通过 import 进行引入 |
| | | export default { |
| | | judgeIosPermission: judgeIosPermission, |
| | | requestAndroidPermission: requestAndroidPermission, |
| | | checkSystemEnableLocation: checkSystemEnableLocation, |
| | | gotoAppPermissionSetting: gotoAppPermissionSetting |
| | | }; |
| | | |
| New file |
| | |
| | | <template> |
| | | <TRTCCloudUniPlugin-TXLocalViewComponent :viewId="viewId"></TRTCCloudUniPlugin-TXLocalViewComponent> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'TrtcLocalView', |
| | | props: { |
| | | viewId: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <TRTCCloudUniPlugin-TXRemoteViewComponent :userId="userId" :viewId="viewId"></TRTCCloudUniPlugin-TXRemoteViewComponent> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'TrtcRemoteView', |
| | | props: { |
| | | userId: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | viewId: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | |
| | | </style> |
| New file |
| | |
| | | // #ifdef APP-PLUS |
| | | import TrtcCloud from '@/utils/voiceCallByTX/TrtcCloud/lib/index'; |
| | | import {TRTCAppScene} from '@/utils/voiceCallByTX/TrtcCloud/lib/TrtcDefines'; |
| | | |
| | | const trtcCloud = TrtcCloud.createInstance(); |
| | | // #endif |
| | | |
| | | // #ifdef H5 |
| | | import TRTC from 'trtc-sdk-v5'; |
| | | |
| | | const trtc = TRTC.create(); |
| | | // #endif |
| | | |
| | | import {genTestUserSig} from "@/utils/voiceCallByTX/GenerateTestUserSig.js"; |
| | | import {sendVoiceCallApi} from "@/api/user/index.js"; |
| | | |
| | | export function enterRoom(payload, userId) { |
| | | const data = JSON.parse(payload.data.data) |
| | | const theOtherPartyId = payload.data.caller_id |
| | | const {userSig, SDKAppID: sdkAppId} = genTestUserSig(userId); |
| | | const params = {sdkAppId, userId, roomId: data.roomId, userSig}; |
| | | // #ifdef APP-PLUS |
| | | trtcCloud.enterRoom(params, TRTCAppScene.TRTCAppSceneVideoCall) |
| | | trtcCloud.startLocalAudio(); |
| | | // #endif |
| | | // #ifdef H5 |
| | | trtc.enterRoom(params) |
| | | trtc.startLocalAudio() |
| | | // #endif |
| | | // demo原因,直接接通来进行验证测试 |
| | | sendVoiceCallApi({ |
| | | caller_id: userId, |
| | | receiver_id: theOtherPartyId, |
| | | data: JSON.stringify({state: '接通', roomId: data.roomId}), |
| | | }) |
| | | } |
| New file |
| | |
| | | /*eslint-disable*/ |
| | | var e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},t=[],r=[],n="undefined"!=typeof Uint8Array?Uint8Array:Array,i=!1;function o(){i=!0;for(var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=0,o=e.length;n<o;++n)t[n]=e[n],r[e.charCodeAt(n)]=n;r["-".charCodeAt(0)]=62,r["_".charCodeAt(0)]=63}function a(e,r,n){for(var i,o,a=[],s=r;s<n;s+=3)i=(e[s]<<16)+(e[s+1]<<8)+e[s+2],a.push(t[(o=i)>>18&63]+t[o>>12&63]+t[o>>6&63]+t[63&o]);return a.join("")}function s(e){var r;i||o();for(var n=e.length,s=n%3,h="",l=[],f=0,c=n-s;f<c;f+=16383)l.push(a(e,f,f+16383>c?c:f+16383));return 1===s?(r=e[n-1],h+=t[r>>2],h+=t[r<<4&63],h+="=="):2===s&&(r=(e[n-2]<<8)+e[n-1],h+=t[r>>10],h+=t[r>>4&63],h+=t[r<<2&63],h+="="),l.push(h),l.join("")}function h(e,t,r,n,i){var o,a,s=8*i-n-1,h=(1<<s)-1,l=h>>1,f=-7,c=r?i-1:0,u=r?-1:1,d=e[t+c];for(c+=u,o=d&(1<<-f)-1,d>>=-f,f+=s;f>0;o=256*o+e[t+c],c+=u,f-=8);for(a=o&(1<<-f)-1,o>>=-f,f+=n;f>0;a=256*a+e[t+c],c+=u,f-=8);if(0===o)o=1-l;else{if(o===h)return a?NaN:1/0*(d?-1:1);a+=Math.pow(2,n),o-=l}return(d?-1:1)*a*Math.pow(2,o-n)}function l(e,t,r,n,i,o){var a,s,h,l=8*o-i-1,f=(1<<l)-1,c=f>>1,u=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,d=n?0:o-1,p=n?1:-1,_=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=f):(a=Math.floor(Math.log(t)/Math.LN2),t*(h=Math.pow(2,-a))<1&&(a--,h*=2),(t+=a+c>=1?u/h:u*Math.pow(2,1-c))*h>=2&&(a++,h/=2),a+c>=f?(s=0,a=f):a+c>=1?(s=(t*h-1)*Math.pow(2,i),a+=c):(s=t*Math.pow(2,c-1)*Math.pow(2,i),a=0));i>=8;e[r+d]=255&s,d+=p,s/=256,i-=8);for(a=a<<i|s,l+=i;l>0;e[r+d]=255&a,d+=p,a/=256,l-=8);e[r+d-p]|=128*_}var f={}.toString,c=Array.isArray||function(e){return"[object Array]"==f.call(e)};function u(){return p.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function d(e,t){if(u()<t)throw new RangeError("Invalid typed array length");return p.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=p.prototype:(null===e&&(e=new p(t)),e.length=t),e}function p(e,t,r){if(!(p.TYPED_ARRAY_SUPPORT||this instanceof p))return new p(e,t,r);if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return v(this,e)}return _(this,e,t,r)}function _(e,t,r,n){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,r,n){if(t.byteLength,r<0||t.byteLength<r)throw new RangeError("'offset' is out of bounds");if(t.byteLength<r+(n||0))throw new RangeError("'length' is out of bounds");t=void 0===r&&void 0===n?new Uint8Array(t):void 0===n?new Uint8Array(t,r):new Uint8Array(t,r,n);p.TYPED_ARRAY_SUPPORT?(e=t).__proto__=p.prototype:e=w(e,t);return e}(e,t,r,n):"string"==typeof t?function(e,t,r){"string"==typeof r&&""!==r||(r="utf8");if(!p.isEncoding(r))throw new TypeError('"encoding" must be a valid string encoding');var n=0|m(t,r),i=(e=d(e,n)).write(t,r);i!==n&&(e=e.slice(0,i));return e}(e,t,r):function(e,t){if(y(t)){var r=0|b(t.length);return 0===(e=d(e,r)).length?e:(t.copy(e,0,0,r),e)}if(t){if("undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return"number"!=typeof t.length||(n=t.length)!=n?d(e,0):w(e,t);if("Buffer"===t.type&&c(t.data))return w(e,t.data)}var n;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(e,t)}function g(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function v(e,t){if(g(t),e=d(e,t<0?0:0|b(t)),!p.TYPED_ARRAY_SUPPORT)for(var r=0;r<t;++r)e[r]=0;return e}function w(e,t){var r=t.length<0?0:0|b(t.length);e=d(e,r);for(var n=0;n<r;n+=1)e[n]=255&t[n];return e}function b(e){if(e>=u())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+u().toString(16)+" bytes");return 0|e}function y(e){return!(null==e||!e._isBuffer)}function m(e,t){if(y(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var r=e.length;if(0===r)return 0;for(var n=!1;;)switch(t){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return q(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return V(e).length;default:if(n)return q(e).length;t=(""+t).toLowerCase(),n=!0}}function k(e,t,r){var n=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return O(this,t,r);case"utf8":case"utf-8":return C(this,t,r);case"ascii":return I(this,t,r);case"latin1":case"binary":return P(this,t,r);case"base64":return M(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return U(this,t,r);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}}function E(e,t,r){var n=e[t];e[t]=e[r],e[r]=n}function S(e,t,r,n,i){if(0===e.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),r=+r,isNaN(r)&&(r=i?0:e.length-1),r<0&&(r=e.length+r),r>=e.length){if(i)return-1;r=e.length-1}else if(r<0){if(!i)return-1;r=0}if("string"==typeof t&&(t=p.from(t,n)),y(t))return 0===t.length?-1:x(e,t,r,n,i);if("number"==typeof t)return t&=255,p.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(e,t,r):Uint8Array.prototype.lastIndexOf.call(e,t,r):x(e,[t],r,n,i);throw new TypeError("val must be string, number or Buffer")}function x(e,t,r,n,i){var o,a=1,s=e.length,h=t.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(e.length<2||t.length<2)return-1;a=2,s/=2,h/=2,r/=2}function l(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(i){var f=-1;for(o=r;o<s;o++)if(l(e,o)===l(t,-1===f?0:o-f)){if(-1===f&&(f=o),o-f+1===h)return f*a}else-1!==f&&(o-=o-f),f=-1}else for(r+h>s&&(r=s-h),o=r;o>=0;o--){for(var c=!0,u=0;u<h;u++)if(l(e,o+u)!==l(t,u)){c=!1;break}if(c)return o}return-1}function R(e,t,r,n){r=Number(r)||0;var i=e.length-r;n?(n=Number(n))>i&&(n=i):n=i;var o=t.length;if(o%2!=0)throw new TypeError("Invalid hex string");n>o/2&&(n=o/2);for(var a=0;a<n;++a){var s=parseInt(t.substr(2*a,2),16);if(isNaN(s))return a;e[r+a]=s}return a}function A(e,t,r,n){return G(q(t,e.length-r),e,r,n)}function B(e,t,r,n){return G(function(e){for(var t=[],r=0;r<e.length;++r)t.push(255&e.charCodeAt(r));return t}(t),e,r,n)}function z(e,t,r,n){return B(e,t,r,n)}function L(e,t,r,n){return G(V(t),e,r,n)}function T(e,t,r,n){return G(function(e,t){for(var r,n,i,o=[],a=0;a<e.length&&!((t-=2)<0);++a)r=e.charCodeAt(a),n=r>>8,i=r%256,o.push(i),o.push(n);return o}(t,e.length-r),e,r,n)}function M(e,t,r){return 0===t&&r===e.length?s(e):s(e.slice(t,r))}function C(e,t,r){r=Math.min(e.length,r);for(var n=[],i=t;i<r;){var o,a,s,h,l=e[i],f=null,c=l>239?4:l>223?3:l>191?2:1;if(i+c<=r)switch(c){case 1:l<128&&(f=l);break;case 2:128==(192&(o=e[i+1]))&&(h=(31&l)<<6|63&o)>127&&(f=h);break;case 3:o=e[i+1],a=e[i+2],128==(192&o)&&128==(192&a)&&(h=(15&l)<<12|(63&o)<<6|63&a)>2047&&(h<55296||h>57343)&&(f=h);break;case 4:o=e[i+1],a=e[i+2],s=e[i+3],128==(192&o)&&128==(192&a)&&128==(192&s)&&(h=(15&l)<<18|(63&o)<<12|(63&a)<<6|63&s)>65535&&h<1114112&&(f=h)}null===f?(f=65533,c=1):f>65535&&(f-=65536,n.push(f>>>10&1023|55296),f=56320|1023&f),n.push(f),i+=c}return function(e){var t=e.length;if(t<=D)return String.fromCharCode.apply(String,e);var r="",n=0;for(;n<t;)r+=String.fromCharCode.apply(String,e.slice(n,n+=D));return r}(n)}p.TYPED_ARRAY_SUPPORT=void 0===e.TYPED_ARRAY_SUPPORT||e.TYPED_ARRAY_SUPPORT,p.poolSize=8192,p._augment=function(e){return e.__proto__=p.prototype,e},p.from=function(e,t,r){return _(null,e,t,r)},p.TYPED_ARRAY_SUPPORT&&(p.prototype.__proto__=Uint8Array.prototype,p.__proto__=Uint8Array),p.alloc=function(e,t,r){return function(e,t,r,n){return g(t),t<=0?d(e,t):void 0!==r?"string"==typeof n?d(e,t).fill(r,n):d(e,t).fill(r):d(e,t)}(null,e,t,r)},p.allocUnsafe=function(e){return v(null,e)},p.allocUnsafeSlow=function(e){return v(null,e)},p.isBuffer=$,p.compare=function(e,t){if(!y(e)||!y(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var r=e.length,n=t.length,i=0,o=Math.min(r,n);i<o;++i)if(e[i]!==t[i]){r=e[i],n=t[i];break}return r<n?-1:n<r?1:0},p.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},p.concat=function(e,t){if(!c(e))throw new TypeError('"list" argument must be an Array of Buffers');if(0===e.length)return p.alloc(0);var r;if(void 0===t)for(t=0,r=0;r<e.length;++r)t+=e[r].length;var n=p.allocUnsafe(t),i=0;for(r=0;r<e.length;++r){var o=e[r];if(!y(o))throw new TypeError('"list" argument must be an Array of Buffers');o.copy(n,i),i+=o.length}return n},p.byteLength=m,p.prototype._isBuffer=!0,p.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var t=0;t<e;t+=2)E(this,t,t+1);return this},p.prototype.swap32=function(){var e=this.length;if(e%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var t=0;t<e;t+=4)E(this,t,t+3),E(this,t+1,t+2);return this},p.prototype.swap64=function(){var e=this.length;if(e%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var t=0;t<e;t+=8)E(this,t,t+7),E(this,t+1,t+6),E(this,t+2,t+5),E(this,t+3,t+4);return this},p.prototype.toString=function(){var e=0|this.length;return 0===e?"":0===arguments.length?C(this,0,e):k.apply(this,arguments)},p.prototype.equals=function(e){if(!y(e))throw new TypeError("Argument must be a Buffer");return this===e||0===p.compare(this,e)},p.prototype.inspect=function(){var e="";return this.length>0&&(e=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(e+=" ... ")),"<Buffer "+e+">"},p.prototype.compare=function(e,t,r,n,i){if(!y(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===r&&(r=e?e.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),t<0||r>e.length||n<0||i>this.length)throw new RangeError("out of range index");if(n>=i&&t>=r)return 0;if(n>=i)return-1;if(t>=r)return 1;if(this===e)return 0;for(var o=(i>>>=0)-(n>>>=0),a=(r>>>=0)-(t>>>=0),s=Math.min(o,a),h=this.slice(n,i),l=e.slice(t,r),f=0;f<s;++f)if(h[f]!==l[f]){o=h[f],a=l[f];break}return o<a?-1:a<o?1:0},p.prototype.includes=function(e,t,r){return-1!==this.indexOf(e,t,r)},p.prototype.indexOf=function(e,t,r){return S(this,e,t,r,!0)},p.prototype.lastIndexOf=function(e,t,r){return S(this,e,t,r,!1)},p.prototype.write=function(e,t,r,n){if(void 0===t)n="utf8",r=this.length,t=0;else if(void 0===r&&"string"==typeof t)n=t,r=this.length,t=0;else{if(!isFinite(t))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");t|=0,isFinite(r)?(r|=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}var i=this.length-t;if((void 0===r||r>i)&&(r=i),e.length>0&&(r<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var o=!1;;)switch(n){case"hex":return R(this,e,t,r);case"utf8":case"utf-8":return A(this,e,t,r);case"ascii":return B(this,e,t,r);case"latin1":case"binary":return z(this,e,t,r);case"base64":return L(this,e,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return T(this,e,t,r);default:if(o)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),o=!0}},p.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var D=4096;function I(e,t,r){var n="";r=Math.min(e.length,r);for(var i=t;i<r;++i)n+=String.fromCharCode(127&e[i]);return n}function P(e,t,r){var n="";r=Math.min(e.length,r);for(var i=t;i<r;++i)n+=String.fromCharCode(e[i]);return n}function O(e,t,r){var n=e.length;(!t||t<0)&&(t=0),(!r||r<0||r>n)&&(r=n);for(var i="",o=t;o<r;++o)i+=X(e[o]);return i}function U(e,t,r){for(var n=e.slice(t,r),i="",o=0;o<n.length;o+=2)i+=String.fromCharCode(n[o]+256*n[o+1]);return i}function H(e,t,r){if(e%1!=0||e<0)throw new RangeError("offset is not uint");if(e+t>r)throw new RangeError("Trying to access beyond buffer length")}function F(e,t,r,n,i,o){if(!y(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>i||t<o)throw new RangeError('"value" argument is out of bounds');if(r+n>e.length)throw new RangeError("Index out of range")}function N(e,t,r,n){t<0&&(t=65535+t+1);for(var i=0,o=Math.min(e.length-r,2);i<o;++i)e[r+i]=(t&255<<8*(n?i:1-i))>>>8*(n?i:1-i)}function Z(e,t,r,n){t<0&&(t=4294967295+t+1);for(var i=0,o=Math.min(e.length-r,4);i<o;++i)e[r+i]=t>>>8*(n?i:3-i)&255}function j(e,t,r,n,i,o){if(r+n>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function W(e,t,r,n,i){return i||j(e,0,r,4),l(e,t,r,n,23,4),r+4}function Y(e,t,r,n,i){return i||j(e,0,r,8),l(e,t,r,n,52,8),r+8}p.prototype.slice=function(e,t){var r,n=this.length;if((e=~~e)<0?(e+=n)<0&&(e=0):e>n&&(e=n),(t=void 0===t?n:~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),t<e&&(t=e),p.TYPED_ARRAY_SUPPORT)(r=this.subarray(e,t)).__proto__=p.prototype;else{var i=t-e;r=new p(i,void 0);for(var o=0;o<i;++o)r[o]=this[o+e]}return r},p.prototype.readUIntLE=function(e,t,r){e|=0,t|=0,r||H(e,t,this.length);for(var n=this[e],i=1,o=0;++o<t&&(i*=256);)n+=this[e+o]*i;return n},p.prototype.readUIntBE=function(e,t,r){e|=0,t|=0,r||H(e,t,this.length);for(var n=this[e+--t],i=1;t>0&&(i*=256);)n+=this[e+--t]*i;return n},p.prototype.readUInt8=function(e,t){return t||H(e,1,this.length),this[e]},p.prototype.readUInt16LE=function(e,t){return t||H(e,2,this.length),this[e]|this[e+1]<<8},p.prototype.readUInt16BE=function(e,t){return t||H(e,2,this.length),this[e]<<8|this[e+1]},p.prototype.readUInt32LE=function(e,t){return t||H(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},p.prototype.readUInt32BE=function(e,t){return t||H(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},p.prototype.readIntLE=function(e,t,r){e|=0,t|=0,r||H(e,t,this.length);for(var n=this[e],i=1,o=0;++o<t&&(i*=256);)n+=this[e+o]*i;return n>=(i*=128)&&(n-=Math.pow(2,8*t)),n},p.prototype.readIntBE=function(e,t,r){e|=0,t|=0,r||H(e,t,this.length);for(var n=t,i=1,o=this[e+--n];n>0&&(i*=256);)o+=this[e+--n]*i;return o>=(i*=128)&&(o-=Math.pow(2,8*t)),o},p.prototype.readInt8=function(e,t){return t||H(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},p.prototype.readInt16LE=function(e,t){t||H(e,2,this.length);var r=this[e]|this[e+1]<<8;return 32768&r?4294901760|r:r},p.prototype.readInt16BE=function(e,t){t||H(e,2,this.length);var r=this[e+1]|this[e]<<8;return 32768&r?4294901760|r:r},p.prototype.readInt32LE=function(e,t){return t||H(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},p.prototype.readInt32BE=function(e,t){return t||H(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},p.prototype.readFloatLE=function(e,t){return t||H(e,4,this.length),h(this,e,!0,23,4)},p.prototype.readFloatBE=function(e,t){return t||H(e,4,this.length),h(this,e,!1,23,4)},p.prototype.readDoubleLE=function(e,t){return t||H(e,8,this.length),h(this,e,!0,52,8)},p.prototype.readDoubleBE=function(e,t){return t||H(e,8,this.length),h(this,e,!1,52,8)},p.prototype.writeUIntLE=function(e,t,r,n){(e=+e,t|=0,r|=0,n)||F(this,e,t,r,Math.pow(2,8*r)-1,0);var i=1,o=0;for(this[t]=255&e;++o<r&&(i*=256);)this[t+o]=e/i&255;return t+r},p.prototype.writeUIntBE=function(e,t,r,n){(e=+e,t|=0,r|=0,n)||F(this,e,t,r,Math.pow(2,8*r)-1,0);var i=r-1,o=1;for(this[t+i]=255&e;--i>=0&&(o*=256);)this[t+i]=e/o&255;return t+r},p.prototype.writeUInt8=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,1,255,0),p.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},p.prototype.writeUInt16LE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,2,65535,0),p.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},p.prototype.writeUInt16BE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,2,65535,0),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},p.prototype.writeUInt32LE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,4,4294967295,0),p.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):Z(this,e,t,!0),t+4},p.prototype.writeUInt32BE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,4,4294967295,0),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):Z(this,e,t,!1),t+4},p.prototype.writeIntLE=function(e,t,r,n){if(e=+e,t|=0,!n){var i=Math.pow(2,8*r-1);F(this,e,t,r,i-1,-i)}var o=0,a=1,s=0;for(this[t]=255&e;++o<r&&(a*=256);)e<0&&0===s&&0!==this[t+o-1]&&(s=1),this[t+o]=(e/a>>0)-s&255;return t+r},p.prototype.writeIntBE=function(e,t,r,n){if(e=+e,t|=0,!n){var i=Math.pow(2,8*r-1);F(this,e,t,r,i-1,-i)}var o=r-1,a=1,s=0;for(this[t+o]=255&e;--o>=0&&(a*=256);)e<0&&0===s&&0!==this[t+o+1]&&(s=1),this[t+o]=(e/a>>0)-s&255;return t+r},p.prototype.writeInt8=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,1,127,-128),p.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},p.prototype.writeInt16LE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,2,32767,-32768),p.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},p.prototype.writeInt16BE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,2,32767,-32768),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},p.prototype.writeInt32LE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,4,2147483647,-2147483648),p.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):Z(this,e,t,!0),t+4},p.prototype.writeInt32BE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):Z(this,e,t,!1),t+4},p.prototype.writeFloatLE=function(e,t,r){return W(this,e,t,!0,r)},p.prototype.writeFloatBE=function(e,t,r){return W(this,e,t,!1,r)},p.prototype.writeDoubleLE=function(e,t,r){return Y(this,e,t,!0,r)},p.prototype.writeDoubleBE=function(e,t,r){return Y(this,e,t,!1,r)},p.prototype.copy=function(e,t,r,n){if(r||(r=0),n||0===n||(n=this.length),t>=e.length&&(t=e.length),t||(t=0),n>0&&n<r&&(n=r),n===r)return 0;if(0===e.length||0===this.length)return 0;if(t<0)throw new RangeError("targetStart out of bounds");if(r<0||r>=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),e.length-t<n-r&&(n=e.length-t+r);var i,o=n-r;if(this===e&&r<t&&t<n)for(i=o-1;i>=0;--i)e[i+t]=this[i+r];else if(o<1e3||!p.TYPED_ARRAY_SUPPORT)for(i=0;i<o;++i)e[i+t]=this[i+r];else Uint8Array.prototype.set.call(e,this.subarray(r,r+o),t);return o},p.prototype.fill=function(e,t,r,n){if("string"==typeof e){if("string"==typeof t?(n=t,t=0,r=this.length):"string"==typeof r&&(n=r,r=this.length),1===e.length){var i=e.charCodeAt(0);i<256&&(e=i)}if(void 0!==n&&"string"!=typeof n)throw new TypeError("encoding must be a string");if("string"==typeof n&&!p.isEncoding(n))throw new TypeError("Unknown encoding: "+n)}else"number"==typeof e&&(e&=255);if(t<0||this.length<t||this.length<r)throw new RangeError("Out of range index");if(r<=t)return this;var o;if(t>>>=0,r=void 0===r?this.length:r>>>0,e||(e=0),"number"==typeof e)for(o=t;o<r;++o)this[o]=e;else{var a=y(e)?e:q(new p(e,n).toString()),s=a.length;for(o=0;o<r-t;++o)this[o+t]=a[o%s]}return this};var K=/[^+\/0-9A-Za-z-_]/g;function X(e){return e<16?"0"+e.toString(16):e.toString(16)}function q(e,t){var r;t=t||1/0;for(var n=e.length,i=null,o=[],a=0;a<n;++a){if((r=e.charCodeAt(a))>55295&&r<57344){if(!i){if(r>56319){(t-=3)>-1&&o.push(239,191,189);continue}if(a+1===n){(t-=3)>-1&&o.push(239,191,189);continue}i=r;continue}if(r<56320){(t-=3)>-1&&o.push(239,191,189),i=r;continue}r=65536+(i-55296<<10|r-56320)}else i&&(t-=3)>-1&&o.push(239,191,189);if(i=null,r<128){if((t-=1)<0)break;o.push(r)}else if(r<2048){if((t-=2)<0)break;o.push(r>>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;o.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return o}function V(e){return function(e){var t,a,s,h,l,f;i||o();var c=e.length;if(c%4>0)throw new Error("Invalid string. Length must be a multiple of 4");l="="===e[c-2]?2:"="===e[c-1]?1:0,f=new n(3*c/4-l),s=l>0?c-4:c;var u=0;for(t=0,a=0;t<s;t+=4,a+=3)h=r[e.charCodeAt(t)]<<18|r[e.charCodeAt(t+1)]<<12|r[e.charCodeAt(t+2)]<<6|r[e.charCodeAt(t+3)],f[u++]=h>>16&255,f[u++]=h>>8&255,f[u++]=255&h;return 2===l?(h=r[e.charCodeAt(t)]<<2|r[e.charCodeAt(t+1)]>>4,f[u++]=255&h):1===l&&(h=r[e.charCodeAt(t)]<<10|r[e.charCodeAt(t+1)]<<4|r[e.charCodeAt(t+2)]>>2,f[u++]=h>>8&255,f[u++]=255&h),f}(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(K,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function G(e,t,r,n){for(var i=0;i<n&&!(i+r>=t.length||i>=e.length);++i)t[i+r]=e[i];return i}function $(e){return null!=e&&(!!e._isBuffer||J(e)||function(e){return"function"==typeof e.readFloatLE&&"function"==typeof e.slice&&J(e.slice(0,0))}(e))}function J(e){return!!e.constructor&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function Q(e,t){return e(t={exports:{}},t.exports),t.exports}var ee=Q(function(e,t){var r;e.exports=(r=r||function(e,t){var r=Object.create||function(){function e(){}return function(t){var r;return e.prototype=t,r=new e,e.prototype=null,r}}(),n={},i=n.lib={},o=i.Base={extend:function(e){var t=r(this);return e&&t.mixIn(e),t.hasOwnProperty("init")&&this.init!==t.init||(t.init=function(){t.$super.init.apply(this,arguments)}),t.init.prototype=t,t.$super=this,t},create:function(){var e=this.extend();return e.init.apply(e,arguments),e},init:function(){},mixIn:function(e){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);e.hasOwnProperty("toString")&&(this.toString=e.toString)},clone:function(){return this.init.prototype.extend(this)}},a=i.WordArray=o.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:4*e.length},toString:function(e){return(e||h).stringify(this)},concat:function(e){var t=this.words,r=e.words,n=this.sigBytes,i=e.sigBytes;if(this.clamp(),n%4)for(var o=0;o<i;o++){var a=r[o>>>2]>>>24-o%4*8&255;t[n+o>>>2]|=a<<24-(n+o)%4*8}else for(var o=0;o<i;o+=4)t[n+o>>>2]=r[o>>>2];return this.sigBytes+=i,this},clamp:function(){var t=this.words,r=this.sigBytes;t[r>>>2]&=4294967295<<32-r%4*8,t.length=e.ceil(r/4)},clone:function(){var e=o.clone.call(this);return e.words=this.words.slice(0),e},random:function(t){for(var r,n=[],i=function(t){var t=t,r=987654321,n=4294967295;return function(){var i=((r=36969*(65535&r)+(r>>16)&n)<<16)+(t=18e3*(65535&t)+(t>>16)&n)&n;return i/=4294967296,(i+=.5)*(e.random()>.5?1:-1)}},o=0;o<t;o+=4){var s=i(4294967296*(r||e.random()));r=987654071*s(),n.push(4294967296*s()|0)}return new a.init(n,t)}}),s=n.enc={},h=s.Hex={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i<r;i++){var o=t[i>>>2]>>>24-i%4*8&255;n.push((o>>>4).toString(16)),n.push((15&o).toString(16))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n<t;n+=2)r[n>>>3]|=parseInt(e.substr(n,2),16)<<24-n%8*4;return new a.init(r,t/2)}},l=s.Latin1={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i<r;i++){var o=t[i>>>2]>>>24-i%4*8&255;n.push(String.fromCharCode(o))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n<t;n++)r[n>>>2]|=(255&e.charCodeAt(n))<<24-n%4*8;return new a.init(r,t)}},f=s.Utf8={stringify:function(e){try{return decodeURIComponent(escape(l.stringify(e)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(e){return l.parse(unescape(encodeURIComponent(e)))}},c=i.BufferedBlockAlgorithm=o.extend({reset:function(){this._data=new a.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=f.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(t){var r=this._data,n=r.words,i=r.sigBytes,o=this.blockSize,s=4*o,h=i/s,l=(h=t?e.ceil(h):e.max((0|h)-this._minBufferSize,0))*o,f=e.min(4*l,i);if(l){for(var c=0;c<l;c+=o)this._doProcessBlock(n,c);var u=n.splice(0,l);r.sigBytes-=f}return new a.init(u,f)},clone:function(){var e=o.clone.call(this);return e._data=this._data.clone(),e},_minBufferSize:0}),u=(i.Hasher=c.extend({cfg:o.extend(),init:function(e){this.cfg=this.cfg.extend(e),this.reset()},reset:function(){c.reset.call(this),this._doReset()},update:function(e){return this._append(e),this._process(),this},finalize:function(e){e&&this._append(e);var t=this._doFinalize();return t},blockSize:16,_createHelper:function(e){return function(t,r){return new e.init(r).finalize(t)}},_createHmacHelper:function(e){return function(t,r){return new u.HMAC.init(e,r).finalize(t)}}}),n.algo={});return n}(Math),r)}),te=(Q(function(e,t){var r,n,i,o,a,s;e.exports=(i=(n=r=ee).lib,o=i.Base,a=i.WordArray,(s=n.x64={}).Word=o.extend({init:function(e,t){this.high=e,this.low=t}}),s.WordArray=o.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:8*e.length},toX32:function(){for(var e=this.words,t=e.length,r=[],n=0;n<t;n++){var i=e[n];r.push(i.high),r.push(i.low)}return a.create(r,this.sigBytes)},clone:function(){for(var e=o.clone.call(this),t=e.words=this.words.slice(0),r=t.length,n=0;n<r;n++)t[n]=t[n].clone();return e}}),r)}),Q(function(e,t){var r;e.exports=(r=ee,function(){if("function"==typeof ArrayBuffer){var e=r.lib.WordArray,t=e.init;(e.init=function(e){if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),(e instanceof Int8Array||"undefined"!=typeof Uint8ClampedArray&&e instanceof Uint8ClampedArray||e instanceof Int16Array||e instanceof Uint16Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Float32Array||e instanceof Float64Array)&&(e=new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),e instanceof Uint8Array){for(var r=e.byteLength,n=[],i=0;i<r;i++)n[i>>>2]|=e[i]<<24-i%4*8;t.call(this,n,r)}else t.apply(this,arguments)}).prototype=e}}(),r.lib.WordArray)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.WordArray,n=e.enc;function i(e){return e<<8&4278255360|e>>>8&16711935}n.Utf16=n.Utf16BE={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i<r;i+=2){var o=t[i>>>2]>>>16-i%4*8&65535;n.push(String.fromCharCode(o))}return n.join("")},parse:function(e){for(var r=e.length,n=[],i=0;i<r;i++)n[i>>>1]|=e.charCodeAt(i)<<16-i%2*16;return t.create(n,2*r)}},n.Utf16LE={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],o=0;o<r;o+=2){var a=i(t[o>>>2]>>>16-o%4*8&65535);n.push(String.fromCharCode(a))}return n.join("")},parse:function(e){for(var r=e.length,n=[],o=0;o<r;o++)n[o>>>1]|=i(e.charCodeAt(o)<<16-o%2*16);return t.create(n,2*r)}}}(),r.enc.Utf16)}),Q(function(e,t){var r,n,i;e.exports=(i=(n=r=ee).lib.WordArray,n.enc.Base64={stringify:function(e){var t=e.words,r=e.sigBytes,n=this._map;e.clamp();for(var i=[],o=0;o<r;o+=3)for(var a=(t[o>>>2]>>>24-o%4*8&255)<<16|(t[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|t[o+2>>>2]>>>24-(o+2)%4*8&255,s=0;s<4&&o+.75*s<r;s++)i.push(n.charAt(a>>>6*(3-s)&63));var h=n.charAt(64);if(h)for(;i.length%4;)i.push(h);return i.join("")},parse:function(e){var t=e.length,r=this._map,n=this._reverseMap;if(!n){n=this._reverseMap=[];for(var o=0;o<r.length;o++)n[r.charCodeAt(o)]=o}var a=r.charAt(64);if(a){var s=e.indexOf(a);-1!==s&&(t=s)}return function(e,t,r){for(var n=[],o=0,a=0;a<t;a++)if(a%4){var s=r[e.charCodeAt(a-1)]<<a%4*2,h=r[e.charCodeAt(a)]>>>6-a%4*2;n[o>>>2]|=(s|h)<<24-o%4*8,o++}return i.create(n,o)}(e,t,n)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},r.enc.Base64)}),Q(function(e,t){var r;e.exports=(r=ee,function(e){var t=r,n=t.lib,i=n.WordArray,o=n.Hasher,a=t.algo,s=[];!function(){for(var t=0;t<64;t++)s[t]=4294967296*e.abs(e.sin(t+1))|0}();var h=a.MD5=o.extend({_doReset:function(){this._hash=new i.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(e,t){for(var r=0;r<16;r++){var n=t+r,i=e[n];e[n]=16711935&(i<<8|i>>>24)|4278255360&(i<<24|i>>>8)}var o=this._hash.words,a=e[t+0],h=e[t+1],d=e[t+2],p=e[t+3],_=e[t+4],g=e[t+5],v=e[t+6],w=e[t+7],b=e[t+8],y=e[t+9],m=e[t+10],k=e[t+11],E=e[t+12],S=e[t+13],x=e[t+14],R=e[t+15],A=o[0],B=o[1],z=o[2],L=o[3];A=l(A,B,z,L,a,7,s[0]),L=l(L,A,B,z,h,12,s[1]),z=l(z,L,A,B,d,17,s[2]),B=l(B,z,L,A,p,22,s[3]),A=l(A,B,z,L,_,7,s[4]),L=l(L,A,B,z,g,12,s[5]),z=l(z,L,A,B,v,17,s[6]),B=l(B,z,L,A,w,22,s[7]),A=l(A,B,z,L,b,7,s[8]),L=l(L,A,B,z,y,12,s[9]),z=l(z,L,A,B,m,17,s[10]),B=l(B,z,L,A,k,22,s[11]),A=l(A,B,z,L,E,7,s[12]),L=l(L,A,B,z,S,12,s[13]),z=l(z,L,A,B,x,17,s[14]),A=f(A,B=l(B,z,L,A,R,22,s[15]),z,L,h,5,s[16]),L=f(L,A,B,z,v,9,s[17]),z=f(z,L,A,B,k,14,s[18]),B=f(B,z,L,A,a,20,s[19]),A=f(A,B,z,L,g,5,s[20]),L=f(L,A,B,z,m,9,s[21]),z=f(z,L,A,B,R,14,s[22]),B=f(B,z,L,A,_,20,s[23]),A=f(A,B,z,L,y,5,s[24]),L=f(L,A,B,z,x,9,s[25]),z=f(z,L,A,B,p,14,s[26]),B=f(B,z,L,A,b,20,s[27]),A=f(A,B,z,L,S,5,s[28]),L=f(L,A,B,z,d,9,s[29]),z=f(z,L,A,B,w,14,s[30]),A=c(A,B=f(B,z,L,A,E,20,s[31]),z,L,g,4,s[32]),L=c(L,A,B,z,b,11,s[33]),z=c(z,L,A,B,k,16,s[34]),B=c(B,z,L,A,x,23,s[35]),A=c(A,B,z,L,h,4,s[36]),L=c(L,A,B,z,_,11,s[37]),z=c(z,L,A,B,w,16,s[38]),B=c(B,z,L,A,m,23,s[39]),A=c(A,B,z,L,S,4,s[40]),L=c(L,A,B,z,a,11,s[41]),z=c(z,L,A,B,p,16,s[42]),B=c(B,z,L,A,v,23,s[43]),A=c(A,B,z,L,y,4,s[44]),L=c(L,A,B,z,E,11,s[45]),z=c(z,L,A,B,R,16,s[46]),A=u(A,B=c(B,z,L,A,d,23,s[47]),z,L,a,6,s[48]),L=u(L,A,B,z,w,10,s[49]),z=u(z,L,A,B,x,15,s[50]),B=u(B,z,L,A,g,21,s[51]),A=u(A,B,z,L,E,6,s[52]),L=u(L,A,B,z,p,10,s[53]),z=u(z,L,A,B,m,15,s[54]),B=u(B,z,L,A,h,21,s[55]),A=u(A,B,z,L,b,6,s[56]),L=u(L,A,B,z,R,10,s[57]),z=u(z,L,A,B,v,15,s[58]),B=u(B,z,L,A,S,21,s[59]),A=u(A,B,z,L,_,6,s[60]),L=u(L,A,B,z,k,10,s[61]),z=u(z,L,A,B,d,15,s[62]),B=u(B,z,L,A,y,21,s[63]),o[0]=o[0]+A|0,o[1]=o[1]+B|0,o[2]=o[2]+z|0,o[3]=o[3]+L|0},_doFinalize:function(){var t=this._data,r=t.words,n=8*this._nDataBytes,i=8*t.sigBytes;r[i>>>5]|=128<<24-i%32;var o=e.floor(n/4294967296),a=n;r[15+(i+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),r[14+(i+64>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),t.sigBytes=4*(r.length+1),this._process();for(var s=this._hash,h=s.words,l=0;l<4;l++){var f=h[l];h[l]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return s},clone:function(){var e=o.clone.call(this);return e._hash=this._hash.clone(),e}});function l(e,t,r,n,i,o,a){var s=e+(t&r|~t&n)+i+a;return(s<<o|s>>>32-o)+t}function f(e,t,r,n,i,o,a){var s=e+(t&n|r&~n)+i+a;return(s<<o|s>>>32-o)+t}function c(e,t,r,n,i,o,a){var s=e+(t^r^n)+i+a;return(s<<o|s>>>32-o)+t}function u(e,t,r,n,i,o,a){var s=e+(r^(t|~n))+i+a;return(s<<o|s>>>32-o)+t}t.MD5=o._createHelper(h),t.HmacMD5=o._createHmacHelper(h)}(Math),r.MD5)}),Q(function(e,t){var r,n,i,o,a,s,h,l;e.exports=(i=(n=r=ee).lib,o=i.WordArray,a=i.Hasher,s=n.algo,h=[],l=s.SHA1=a.extend({_doReset:function(){this._hash=new o.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(e,t){for(var r=this._hash.words,n=r[0],i=r[1],o=r[2],a=r[3],s=r[4],l=0;l<80;l++){if(l<16)h[l]=0|e[t+l];else{var f=h[l-3]^h[l-8]^h[l-14]^h[l-16];h[l]=f<<1|f>>>31}var c=(n<<5|n>>>27)+s+h[l];c+=l<20?1518500249+(i&o|~i&a):l<40?1859775393+(i^o^a):l<60?(i&o|i&a|o&a)-1894007588:(i^o^a)-899497514,s=a,a=o,o=i<<30|i>>>2,i=n,n=c}r[0]=r[0]+n|0,r[1]=r[1]+i|0,r[2]=r[2]+o|0,r[3]=r[3]+a|0,r[4]=r[4]+s|0},_doFinalize:function(){var e=this._data,t=e.words,r=8*this._nDataBytes,n=8*e.sigBytes;return t[n>>>5]|=128<<24-n%32,t[14+(n+64>>>9<<4)]=Math.floor(r/4294967296),t[15+(n+64>>>9<<4)]=r,e.sigBytes=4*t.length,this._process(),this._hash},clone:function(){var e=a.clone.call(this);return e._hash=this._hash.clone(),e}}),n.SHA1=a._createHelper(l),n.HmacSHA1=a._createHmacHelper(l),r.SHA1)}),Q(function(e,t){var r;e.exports=(r=ee,function(e){var t=r,n=t.lib,i=n.WordArray,o=n.Hasher,a=t.algo,s=[],h=[];!function(){function t(t){for(var r=e.sqrt(t),n=2;n<=r;n++)if(!(t%n))return!1;return!0}function r(e){return 4294967296*(e-(0|e))|0}for(var n=2,i=0;i<64;)t(n)&&(i<8&&(s[i]=r(e.pow(n,.5))),h[i]=r(e.pow(n,1/3)),i++),n++}();var l=[],f=a.SHA256=o.extend({_doReset:function(){this._hash=new i.init(s.slice(0))},_doProcessBlock:function(e,t){for(var r=this._hash.words,n=r[0],i=r[1],o=r[2],a=r[3],s=r[4],f=r[5],c=r[6],u=r[7],d=0;d<64;d++){if(d<16)l[d]=0|e[t+d];else{var p=l[d-15],_=(p<<25|p>>>7)^(p<<14|p>>>18)^p>>>3,g=l[d-2],v=(g<<15|g>>>17)^(g<<13|g>>>19)^g>>>10;l[d]=_+l[d-7]+v+l[d-16]}var w=n&i^n&o^i&o,b=(n<<30|n>>>2)^(n<<19|n>>>13)^(n<<10|n>>>22),y=u+((s<<26|s>>>6)^(s<<21|s>>>11)^(s<<7|s>>>25))+(s&f^~s&c)+h[d]+l[d];u=c,c=f,f=s,s=a+y|0,a=o,o=i,i=n,n=y+(b+w)|0}r[0]=r[0]+n|0,r[1]=r[1]+i|0,r[2]=r[2]+o|0,r[3]=r[3]+a|0,r[4]=r[4]+s|0,r[5]=r[5]+f|0,r[6]=r[6]+c|0,r[7]=r[7]+u|0},_doFinalize:function(){var t=this._data,r=t.words,n=8*this._nDataBytes,i=8*t.sigBytes;return r[i>>>5]|=128<<24-i%32,r[14+(i+64>>>9<<4)]=e.floor(n/4294967296),r[15+(i+64>>>9<<4)]=n,t.sigBytes=4*r.length,this._process(),this._hash},clone:function(){var e=o.clone.call(this);return e._hash=this._hash.clone(),e}});t.SHA256=o._createHelper(f),t.HmacSHA256=o._createHmacHelper(f)}(Math),r.SHA256)}),Q(function(e,t){var r,n,i,o,a,s;e.exports=(i=(n=r=ee).lib.WordArray,o=n.algo,a=o.SHA256,s=o.SHA224=a.extend({_doReset:function(){this._hash=new i.init([3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428])},_doFinalize:function(){var e=a._doFinalize.call(this);return e.sigBytes-=4,e}}),n.SHA224=a._createHelper(s),n.HmacSHA224=a._createHmacHelper(s),r.SHA224)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.Hasher,n=e.x64,i=n.Word,o=n.WordArray,a=e.algo;function s(){return i.create.apply(i,arguments)}var h=[s(1116352408,3609767458),s(1899447441,602891725),s(3049323471,3964484399),s(3921009573,2173295548),s(961987163,4081628472),s(1508970993,3053834265),s(2453635748,2937671579),s(2870763221,3664609560),s(3624381080,2734883394),s(310598401,1164996542),s(607225278,1323610764),s(1426881987,3590304994),s(1925078388,4068182383),s(2162078206,991336113),s(2614888103,633803317),s(3248222580,3479774868),s(3835390401,2666613458),s(4022224774,944711139),s(264347078,2341262773),s(604807628,2007800933),s(770255983,1495990901),s(1249150122,1856431235),s(1555081692,3175218132),s(1996064986,2198950837),s(2554220882,3999719339),s(2821834349,766784016),s(2952996808,2566594879),s(3210313671,3203337956),s(3336571891,1034457026),s(3584528711,2466948901),s(113926993,3758326383),s(338241895,168717936),s(666307205,1188179964),s(773529912,1546045734),s(1294757372,1522805485),s(1396182291,2643833823),s(1695183700,2343527390),s(1986661051,1014477480),s(2177026350,1206759142),s(2456956037,344077627),s(2730485921,1290863460),s(2820302411,3158454273),s(3259730800,3505952657),s(3345764771,106217008),s(3516065817,3606008344),s(3600352804,1432725776),s(4094571909,1467031594),s(275423344,851169720),s(430227734,3100823752),s(506948616,1363258195),s(659060556,3750685593),s(883997877,3785050280),s(958139571,3318307427),s(1322822218,3812723403),s(1537002063,2003034995),s(1747873779,3602036899),s(1955562222,1575990012),s(2024104815,1125592928),s(2227730452,2716904306),s(2361852424,442776044),s(2428436474,593698344),s(2756734187,3733110249),s(3204031479,2999351573),s(3329325298,3815920427),s(3391569614,3928383900),s(3515267271,566280711),s(3940187606,3454069534),s(4118630271,4000239992),s(116418474,1914138554),s(174292421,2731055270),s(289380356,3203993006),s(460393269,320620315),s(685471733,587496836),s(852142971,1086792851),s(1017036298,365543100),s(1126000580,2618297676),s(1288033470,3409855158),s(1501505948,4234509866),s(1607167915,987167468),s(1816402316,1246189591)],l=[];!function(){for(var e=0;e<80;e++)l[e]=s()}();var f=a.SHA512=t.extend({_doReset:function(){this._hash=new o.init([new i.init(1779033703,4089235720),new i.init(3144134277,2227873595),new i.init(1013904242,4271175723),new i.init(2773480762,1595750129),new i.init(1359893119,2917565137),new i.init(2600822924,725511199),new i.init(528734635,4215389547),new i.init(1541459225,327033209)])},_doProcessBlock:function(e,t){for(var r=this._hash.words,n=r[0],i=r[1],o=r[2],a=r[3],s=r[4],f=r[5],c=r[6],u=r[7],d=n.high,p=n.low,_=i.high,g=i.low,v=o.high,w=o.low,b=a.high,y=a.low,m=s.high,k=s.low,E=f.high,S=f.low,x=c.high,R=c.low,A=u.high,B=u.low,z=d,L=p,T=_,M=g,C=v,D=w,I=b,P=y,O=m,U=k,H=E,F=S,N=x,Z=R,j=A,W=B,Y=0;Y<80;Y++){var K=l[Y];if(Y<16)var X=K.high=0|e[t+2*Y],q=K.low=0|e[t+2*Y+1];else{var V=l[Y-15],G=V.high,$=V.low,J=(G>>>1|$<<31)^(G>>>8|$<<24)^G>>>7,Q=($>>>1|G<<31)^($>>>8|G<<24)^($>>>7|G<<25),ee=l[Y-2],te=ee.high,re=ee.low,ne=(te>>>19|re<<13)^(te<<3|re>>>29)^te>>>6,ie=(re>>>19|te<<13)^(re<<3|te>>>29)^(re>>>6|te<<26),oe=l[Y-7],ae=oe.high,se=oe.low,he=l[Y-16],le=he.high,fe=he.low;X=(X=(X=J+ae+((q=Q+se)>>>0<Q>>>0?1:0))+ne+((q+=ie)>>>0<ie>>>0?1:0))+le+((q+=fe)>>>0<fe>>>0?1:0),K.high=X,K.low=q}var ce,ue=O&H^~O&N,de=U&F^~U&Z,pe=z&T^z&C^T&C,_e=L&M^L&D^M&D,ge=(z>>>28|L<<4)^(z<<30|L>>>2)^(z<<25|L>>>7),ve=(L>>>28|z<<4)^(L<<30|z>>>2)^(L<<25|z>>>7),we=(O>>>14|U<<18)^(O>>>18|U<<14)^(O<<23|U>>>9),be=(U>>>14|O<<18)^(U>>>18|O<<14)^(U<<23|O>>>9),ye=h[Y],me=ye.high,ke=ye.low,Ee=j+we+((ce=W+be)>>>0<W>>>0?1:0),Se=ve+_e;j=N,W=Z,N=H,Z=F,H=O,F=U,O=I+(Ee=(Ee=(Ee=Ee+ue+((ce+=de)>>>0<de>>>0?1:0))+me+((ce+=ke)>>>0<ke>>>0?1:0))+X+((ce+=q)>>>0<q>>>0?1:0))+((U=P+ce|0)>>>0<P>>>0?1:0)|0,I=C,P=D,C=T,D=M,T=z,M=L,z=Ee+(ge+pe+(Se>>>0<ve>>>0?1:0))+((L=ce+Se|0)>>>0<ce>>>0?1:0)|0}p=n.low=p+L,n.high=d+z+(p>>>0<L>>>0?1:0),g=i.low=g+M,i.high=_+T+(g>>>0<M>>>0?1:0),w=o.low=w+D,o.high=v+C+(w>>>0<D>>>0?1:0),y=a.low=y+P,a.high=b+I+(y>>>0<P>>>0?1:0),k=s.low=k+U,s.high=m+O+(k>>>0<U>>>0?1:0),S=f.low=S+F,f.high=E+H+(S>>>0<F>>>0?1:0),R=c.low=R+Z,c.high=x+N+(R>>>0<Z>>>0?1:0),B=u.low=B+W,u.high=A+j+(B>>>0<W>>>0?1:0)},_doFinalize:function(){var e=this._data,t=e.words,r=8*this._nDataBytes,n=8*e.sigBytes;return t[n>>>5]|=128<<24-n%32,t[30+(n+128>>>10<<5)]=Math.floor(r/4294967296),t[31+(n+128>>>10<<5)]=r,e.sigBytes=4*t.length,this._process(),this._hash.toX32()},clone:function(){var e=t.clone.call(this);return e._hash=this._hash.clone(),e},blockSize:32});e.SHA512=t._createHelper(f),e.HmacSHA512=t._createHmacHelper(f)}(),r.SHA512)}),Q(function(e,t){var r,n,i,o,a,s,h,l;e.exports=(i=(n=r=ee).x64,o=i.Word,a=i.WordArray,s=n.algo,h=s.SHA512,l=s.SHA384=h.extend({_doReset:function(){this._hash=new a.init([new o.init(3418070365,3238371032),new o.init(1654270250,914150663),new o.init(2438529370,812702999),new o.init(355462360,4144912697),new o.init(1731405415,4290775857),new o.init(2394180231,1750603025),new o.init(3675008525,1694076839),new o.init(1203062813,3204075428)])},_doFinalize:function(){var e=h._doFinalize.call(this);return e.sigBytes-=16,e}}),n.SHA384=h._createHelper(l),n.HmacSHA384=h._createHmacHelper(l),r.SHA384)}),Q(function(e,t){var r;e.exports=(r=ee,function(e){var t=r,n=t.lib,i=n.WordArray,o=n.Hasher,a=t.x64.Word,s=t.algo,h=[],l=[],f=[];!function(){for(var e=1,t=0,r=0;r<24;r++){h[e+5*t]=(r+1)*(r+2)/2%64;var n=(2*e+3*t)%5;e=t%5,t=n}for(e=0;e<5;e++)for(t=0;t<5;t++)l[e+5*t]=t+(2*e+3*t)%5*5;for(var i=1,o=0;o<24;o++){for(var s=0,c=0,u=0;u<7;u++){if(1&i){var d=(1<<u)-1;d<32?c^=1<<d:s^=1<<d-32}128&i?i=i<<1^113:i<<=1}f[o]=a.create(s,c)}}();var c=[];!function(){for(var e=0;e<25;e++)c[e]=a.create()}();var u=s.SHA3=o.extend({cfg:o.cfg.extend({outputLength:512}),_doReset:function(){for(var e=this._state=[],t=0;t<25;t++)e[t]=new a.init;this.blockSize=(1600-2*this.cfg.outputLength)/32},_doProcessBlock:function(e,t){for(var r=this._state,n=this.blockSize/2,i=0;i<n;i++){var o=e[t+2*i],a=e[t+2*i+1];o=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),a=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),(B=r[i]).high^=a,B.low^=o}for(var s=0;s<24;s++){for(var u=0;u<5;u++){for(var d=0,p=0,_=0;_<5;_++)d^=(B=r[u+5*_]).high,p^=B.low;var g=c[u];g.high=d,g.low=p}for(u=0;u<5;u++){var v=c[(u+4)%5],w=c[(u+1)%5],b=w.high,y=w.low;for(d=v.high^(b<<1|y>>>31),p=v.low^(y<<1|b>>>31),_=0;_<5;_++)(B=r[u+5*_]).high^=d,B.low^=p}for(var m=1;m<25;m++){var k=(B=r[m]).high,E=B.low,S=h[m];S<32?(d=k<<S|E>>>32-S,p=E<<S|k>>>32-S):(d=E<<S-32|k>>>64-S,p=k<<S-32|E>>>64-S);var x=c[l[m]];x.high=d,x.low=p}var R=c[0],A=r[0];for(R.high=A.high,R.low=A.low,u=0;u<5;u++)for(_=0;_<5;_++){var B=r[m=u+5*_],z=c[m],L=c[(u+1)%5+5*_],T=c[(u+2)%5+5*_];B.high=z.high^~L.high&T.high,B.low=z.low^~L.low&T.low}B=r[0];var M=f[s];B.high^=M.high,B.low^=M.low}},_doFinalize:function(){var t=this._data,r=t.words,n=(this._nDataBytes,8*t.sigBytes),o=32*this.blockSize;r[n>>>5]|=1<<24-n%32,r[(e.ceil((n+1)/o)*o>>>5)-1]|=128,t.sigBytes=4*r.length,this._process();for(var a=this._state,s=this.cfg.outputLength/8,h=s/8,l=[],f=0;f<h;f++){var c=a[f],u=c.high,d=c.low;u=16711935&(u<<8|u>>>24)|4278255360&(u<<24|u>>>8),d=16711935&(d<<8|d>>>24)|4278255360&(d<<24|d>>>8),l.push(d),l.push(u)}return new i.init(l,s)},clone:function(){for(var e=o.clone.call(this),t=e._state=this._state.slice(0),r=0;r<25;r++)t[r]=t[r].clone();return e}});t.SHA3=o._createHelper(u),t.HmacSHA3=o._createHmacHelper(u)}(Math),r.SHA3)}),Q(function(e,t){var r;e.exports=(r=ee,function(e){var t=r,n=t.lib,i=n.WordArray,o=n.Hasher,a=t.algo,s=i.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),h=i.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),l=i.create([11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),f=i.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),c=i.create([0,1518500249,1859775393,2400959708,2840853838]),u=i.create([1352829926,1548603684,1836072691,2053994217,0]),d=a.RIPEMD160=o.extend({_doReset:function(){this._hash=i.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(e,t){for(var r=0;r<16;r++){var n=t+r,i=e[n];e[n]=16711935&(i<<8|i>>>24)|4278255360&(i<<24|i>>>8)}var o,a,d,y,m,k,E,S,x,R,A,B=this._hash.words,z=c.words,L=u.words,T=s.words,M=h.words,C=l.words,D=f.words;for(k=o=B[0],E=a=B[1],S=d=B[2],x=y=B[3],R=m=B[4],r=0;r<80;r+=1)A=o+e[t+T[r]]|0,A+=r<16?p(a,d,y)+z[0]:r<32?_(a,d,y)+z[1]:r<48?g(a,d,y)+z[2]:r<64?v(a,d,y)+z[3]:w(a,d,y)+z[4],A=(A=b(A|=0,C[r]))+m|0,o=m,m=y,y=b(d,10),d=a,a=A,A=k+e[t+M[r]]|0,A+=r<16?w(E,S,x)+L[0]:r<32?v(E,S,x)+L[1]:r<48?g(E,S,x)+L[2]:r<64?_(E,S,x)+L[3]:p(E,S,x)+L[4],A=(A=b(A|=0,D[r]))+R|0,k=R,R=x,x=b(S,10),S=E,E=A;A=B[1]+d+x|0,B[1]=B[2]+y+R|0,B[2]=B[3]+m+k|0,B[3]=B[4]+o+E|0,B[4]=B[0]+a+S|0,B[0]=A},_doFinalize:function(){var e=this._data,t=e.words,r=8*this._nDataBytes,n=8*e.sigBytes;t[n>>>5]|=128<<24-n%32,t[14+(n+64>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),e.sigBytes=4*(t.length+1),this._process();for(var i=this._hash,o=i.words,a=0;a<5;a++){var s=o[a];o[a]=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8)}return i},clone:function(){var e=o.clone.call(this);return e._hash=this._hash.clone(),e}});function p(e,t,r){return e^t^r}function _(e,t,r){return e&t|~e&r}function g(e,t,r){return(e|~t)^r}function v(e,t,r){return e&r|t&~r}function w(e,t,r){return e^(t|~r)}function b(e,t){return e<<t|e>>>32-t}t.RIPEMD160=o._createHelper(d),t.HmacRIPEMD160=o._createHmacHelper(d)}(),r.RIPEMD160)}),Q(function(e,t){var r,n,i,o,a,s;e.exports=(n=(r=ee).lib,i=n.Base,o=r.enc,a=o.Utf8,s=r.algo,void(s.HMAC=i.extend({init:function(e,t){e=this._hasher=new e.init,"string"==typeof t&&(t=a.parse(t));var r=e.blockSize,n=4*r;t.sigBytes>n&&(t=e.finalize(t)),t.clamp();for(var i=this._oKey=t.clone(),o=this._iKey=t.clone(),s=i.words,h=o.words,l=0;l<r;l++)s[l]^=1549556828,h[l]^=909522486;i.sigBytes=o.sigBytes=n,this.reset()},reset:function(){var e=this._hasher;e.reset(),e.update(this._iKey)},update:function(e){return this._hasher.update(e),this},finalize:function(e){var t=this._hasher,r=t.finalize(e);t.reset();var n=t.finalize(this._oKey.clone().concat(r));return n}})))}),Q(function(e,t){var r,n,i,o,a,s,h,l,f;e.exports=(i=(n=r=ee).lib,o=i.Base,a=i.WordArray,s=n.algo,h=s.SHA1,l=s.HMAC,f=s.PBKDF2=o.extend({cfg:o.extend({keySize:4,hasher:h,iterations:1}),init:function(e){this.cfg=this.cfg.extend(e)},compute:function(e,t){for(var r=this.cfg,n=l.create(r.hasher,e),i=a.create(),o=a.create([1]),s=i.words,h=o.words,f=r.keySize,c=r.iterations;s.length<f;){var u=n.update(t).finalize(o);n.reset();for(var d=u.words,p=d.length,_=u,g=1;g<c;g++){_=n.finalize(_),n.reset();for(var v=_.words,w=0;w<p;w++)d[w]^=v[w]}i.concat(u),h[0]++}return i.sigBytes=4*f,i}}),n.PBKDF2=function(e,t,r){return f.create(r).compute(e,t)},r.PBKDF2)}),Q(function(e,t){var r,n,i,o,a,s,h,l;e.exports=(i=(n=r=ee).lib,o=i.Base,a=i.WordArray,s=n.algo,h=s.MD5,l=s.EvpKDF=o.extend({cfg:o.extend({keySize:4,hasher:h,iterations:1}),init:function(e){this.cfg=this.cfg.extend(e)},compute:function(e,t){for(var r=this.cfg,n=r.hasher.create(),i=a.create(),o=i.words,s=r.keySize,h=r.iterations;o.length<s;){l&&n.update(l);var l=n.update(e).finalize(t);n.reset();for(var f=1;f<h;f++)l=n.finalize(l),n.reset();i.concat(l)}return i.sigBytes=4*s,i}}),n.EvpKDF=function(e,t,r){return l.create(r).compute(e,t)},r.EvpKDF)}),Q(function(e,t){var r,n,i,o,a,s,h,l,f,c,u,d,p,_,g,v,w,b,y,m,k,E,S,x;e.exports=void((r=ee).lib.Cipher||(i=r,o=i.lib,a=o.Base,s=o.WordArray,h=o.BufferedBlockAlgorithm,l=i.enc,l.Utf8,f=l.Base64,c=i.algo,u=c.EvpKDF,d=o.Cipher=h.extend({cfg:a.extend(),createEncryptor:function(e,t){return this.create(this._ENC_XFORM_MODE,e,t)},createDecryptor:function(e,t){return this.create(this._DEC_XFORM_MODE,e,t)},init:function(e,t,r){this.cfg=this.cfg.extend(r),this._xformMode=e,this._key=t,this.reset()},reset:function(){h.reset.call(this),this._doReset()},process:function(e){return this._append(e),this._process()},finalize:function(e){e&&this._append(e);var t=this._doFinalize();return t},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){function e(e){return"string"==typeof e?x:k}return function(t){return{encrypt:function(r,n,i){return e(n).encrypt(t,r,n,i)},decrypt:function(r,n,i){return e(n).decrypt(t,r,n,i)}}}}()}),o.StreamCipher=d.extend({_doFinalize:function(){var e=this._process(!0);return e},blockSize:1}),p=i.mode={},_=o.BlockCipherMode=a.extend({createEncryptor:function(e,t){return this.Encryptor.create(e,t)},createDecryptor:function(e,t){return this.Decryptor.create(e,t)},init:function(e,t){this._cipher=e,this._iv=t}}),g=p.CBC=function(){var e=_.extend();function t(e,t,r){var i=this._iv;if(i){var o=i;this._iv=n}else var o=this._prevBlock;for(var a=0;a<r;a++)e[t+a]^=o[a]}return e.Encryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize;t.call(this,e,r,i),n.encryptBlock(e,r),this._prevBlock=e.slice(r,r+i)}}),e.Decryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize,o=e.slice(r,r+i);n.decryptBlock(e,r),t.call(this,e,r,i),this._prevBlock=o}}),e}(),v=i.pad={},w=v.Pkcs7={pad:function(e,t){for(var r=4*t,n=r-e.sigBytes%r,i=n<<24|n<<16|n<<8|n,o=[],a=0;a<n;a+=4)o.push(i);var h=s.create(o,n);e.concat(h)},unpad:function(e){var t=255&e.words[e.sigBytes-1>>>2];e.sigBytes-=t}},o.BlockCipher=d.extend({cfg:d.cfg.extend({mode:g,padding:w}),reset:function(){d.reset.call(this);var e=this.cfg,t=e.iv,r=e.mode;if(this._xformMode==this._ENC_XFORM_MODE)var n=r.createEncryptor;else{var n=r.createDecryptor;this._minBufferSize=1}this._mode&&this._mode.__creator==n?this._mode.init(this,t&&t.words):(this._mode=n.call(r,this,t&&t.words),this._mode.__creator=n)},_doProcessBlock:function(e,t){this._mode.processBlock(e,t)},_doFinalize:function(){var e=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){e.pad(this._data,this.blockSize);var t=this._process(!0)}else{var t=this._process(!0);e.unpad(t)}return t},blockSize:4}),b=o.CipherParams=a.extend({init:function(e){this.mixIn(e)},toString:function(e){return(e||this.formatter).stringify(this)}}),y=i.format={},m=y.OpenSSL={stringify:function(e){var t=e.ciphertext,r=e.salt;if(r)var n=s.create([1398893684,1701076831]).concat(r).concat(t);else var n=t;return n.toString(f)},parse:function(e){var t=f.parse(e),r=t.words;if(1398893684==r[0]&&1701076831==r[1]){var n=s.create(r.slice(2,4));r.splice(0,4),t.sigBytes-=16}return b.create({ciphertext:t,salt:n})}},k=o.SerializableCipher=a.extend({cfg:a.extend({format:m}),encrypt:function(e,t,r,n){n=this.cfg.extend(n);var i=e.createEncryptor(r,n),o=i.finalize(t),a=i.cfg;return b.create({ciphertext:o,key:r,iv:a.iv,algorithm:e,mode:a.mode,padding:a.padding,blockSize:e.blockSize,formatter:n.format})},decrypt:function(e,t,r,n){n=this.cfg.extend(n),t=this._parse(t,n.format);var i=e.createDecryptor(r,n).finalize(t.ciphertext);return i},_parse:function(e,t){return"string"==typeof e?t.parse(e,this):e}}),E=i.kdf={},S=E.OpenSSL={execute:function(e,t,r,n){n||(n=s.random(8));var i=u.create({keySize:t+r}).compute(e,n),o=s.create(i.words.slice(t),4*r);return i.sigBytes=4*t,b.create({key:i,iv:o,salt:n})}},x=o.PasswordBasedCipher=k.extend({cfg:k.cfg.extend({kdf:S}),encrypt:function(e,t,r,n){var i=(n=this.cfg.extend(n)).kdf.execute(r,e.keySize,e.ivSize);n.iv=i.iv;var o=k.encrypt.call(this,e,t,i.key,n);return o.mixIn(i),o},decrypt:function(e,t,r,n){n=this.cfg.extend(n),t=this._parse(t,n.format);var i=n.kdf.execute(r,e.keySize,e.ivSize,t.salt);n.iv=i.iv;var o=k.decrypt.call(this,e,t,i.key,n);return o}})))}),Q(function(e,t){var r;e.exports=((r=ee).mode.CFB=function(){var e=r.lib.BlockCipherMode.extend();function t(e,t,r,n){var i=this._iv;if(i){var o=i.slice(0);this._iv=void 0}else o=this._prevBlock;n.encryptBlock(o,0);for(var a=0;a<r;a++)e[t+a]^=o[a]}return e.Encryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize;t.call(this,e,r,i,n),this._prevBlock=e.slice(r,r+i)}}),e.Decryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize,o=e.slice(r,r+i);t.call(this,e,r,i,n),this._prevBlock=o}}),e}(),r.mode.CFB)}),Q(function(e,t){var r,n,i;e.exports=((r=ee).mode.CTR=(n=r.lib.BlockCipherMode.extend(),i=n.Encryptor=n.extend({processBlock:function(e,t){var r=this._cipher,n=r.blockSize,i=this._iv,o=this._counter;i&&(o=this._counter=i.slice(0),this._iv=void 0);var a=o.slice(0);r.encryptBlock(a,0),o[n-1]=o[n-1]+1|0;for(var s=0;s<n;s++)e[t+s]^=a[s]}}),n.Decryptor=i,n),r.mode.CTR)}),Q(function(e,t){var r;e.exports=((r=ee).mode.CTRGladman=function(){var e=r.lib.BlockCipherMode.extend();function t(e){if(255==(e>>24&255)){var t=e>>16&255,r=e>>8&255,n=255&e;255===t?(t=0,255===r?(r=0,255===n?n=0:++n):++r):++t,e=0,e+=t<<16,e+=r<<8,e+=n}else e+=1<<24;return e}var n=e.Encryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize,o=this._iv,a=this._counter;o&&(a=this._counter=o.slice(0),this._iv=void 0),function(e){0===(e[0]=t(e[0]))&&(e[1]=t(e[1]))}(a);var s=a.slice(0);n.encryptBlock(s,0);for(var h=0;h<i;h++)e[r+h]^=s[h]}});return e.Decryptor=n,e}(),r.mode.CTRGladman)}),Q(function(e,t){var r,n,i;e.exports=((r=ee).mode.OFB=(n=r.lib.BlockCipherMode.extend(),i=n.Encryptor=n.extend({processBlock:function(e,t){var r=this._cipher,n=r.blockSize,i=this._iv,o=this._keystream;i&&(o=this._keystream=i.slice(0),this._iv=void 0),r.encryptBlock(o,0);for(var a=0;a<n;a++)e[t+a]^=o[a]}}),n.Decryptor=i,n),r.mode.OFB)}),Q(function(e,t){var r,n;e.exports=((r=ee).mode.ECB=((n=r.lib.BlockCipherMode.extend()).Encryptor=n.extend({processBlock:function(e,t){this._cipher.encryptBlock(e,t)}}),n.Decryptor=n.extend({processBlock:function(e,t){this._cipher.decryptBlock(e,t)}}),n),r.mode.ECB)}),Q(function(e,t){var r;e.exports=((r=ee).pad.AnsiX923={pad:function(e,t){var r=e.sigBytes,n=4*t,i=n-r%n,o=r+i-1;e.clamp(),e.words[o>>>2]|=i<<24-o%4*8,e.sigBytes+=i},unpad:function(e){var t=255&e.words[e.sigBytes-1>>>2];e.sigBytes-=t}},r.pad.Ansix923)}),Q(function(e,t){var r;e.exports=((r=ee).pad.Iso10126={pad:function(e,t){var n=4*t,i=n-e.sigBytes%n;e.concat(r.lib.WordArray.random(i-1)).concat(r.lib.WordArray.create([i<<24],1))},unpad:function(e){var t=255&e.words[e.sigBytes-1>>>2];e.sigBytes-=t}},r.pad.Iso10126)}),Q(function(e,t){var r;e.exports=((r=ee).pad.Iso97971={pad:function(e,t){e.concat(r.lib.WordArray.create([2147483648],1)),r.pad.ZeroPadding.pad(e,t)},unpad:function(e){r.pad.ZeroPadding.unpad(e),e.sigBytes--}},r.pad.Iso97971)}),Q(function(e,t){var r;e.exports=((r=ee).pad.ZeroPadding={pad:function(e,t){var r=4*t;e.clamp(),e.sigBytes+=r-(e.sigBytes%r||r)},unpad:function(e){for(var t=e.words,r=e.sigBytes-1;!(t[r>>>2]>>>24-r%4*8&255);)r--;e.sigBytes=r+1}},r.pad.ZeroPadding)}),Q(function(e,t){var r;e.exports=((r=ee).pad.NoPadding={pad:function(){},unpad:function(){}},r.pad.NoPadding)}),Q(function(e,t){var r,n,i,o;e.exports=(i=(n=r=ee).lib.CipherParams,o=n.enc.Hex,n.format.Hex={stringify:function(e){return e.ciphertext.toString(o)},parse:function(e){var t=o.parse(e);return i.create({ciphertext:t})}},r.format.Hex)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.BlockCipher,n=e.algo,i=[],o=[],a=[],s=[],h=[],l=[],f=[],c=[],u=[],d=[];!function(){for(var e=[],t=0;t<256;t++)e[t]=t<128?t<<1:t<<1^283;var r=0,n=0;for(t=0;t<256;t++){var p=n^n<<1^n<<2^n<<3^n<<4;p=p>>>8^255&p^99,i[r]=p,o[p]=r;var _=e[r],g=e[_],v=e[g],w=257*e[p]^16843008*p;a[r]=w<<24|w>>>8,s[r]=w<<16|w>>>16,h[r]=w<<8|w>>>24,l[r]=w,w=16843009*v^65537*g^257*_^16843008*r,f[p]=w<<24|w>>>8,c[p]=w<<16|w>>>16,u[p]=w<<8|w>>>24,d[p]=w,r?(r=_^e[e[e[v^_]]],n^=e[e[n]]):r=n=1}}();var p=[0,1,2,4,8,16,32,64,128,27,54],_=n.AES=t.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var e=this._keyPriorReset=this._key,t=e.words,r=e.sigBytes/4,n=4*((this._nRounds=r+6)+1),o=this._keySchedule=[],a=0;a<n;a++)if(a<r)o[a]=t[a];else{var s=o[a-1];a%r?r>6&&a%r==4&&(s=i[s>>>24]<<24|i[s>>>16&255]<<16|i[s>>>8&255]<<8|i[255&s]):(s=i[(s=s<<8|s>>>24)>>>24]<<24|i[s>>>16&255]<<16|i[s>>>8&255]<<8|i[255&s],s^=p[a/r|0]<<24),o[a]=o[a-r]^s}for(var h=this._invKeySchedule=[],l=0;l<n;l++)a=n-l,s=l%4?o[a]:o[a-4],h[l]=l<4||a<=4?s:f[i[s>>>24]]^c[i[s>>>16&255]]^u[i[s>>>8&255]]^d[i[255&s]]}},encryptBlock:function(e,t){this._doCryptBlock(e,t,this._keySchedule,a,s,h,l,i)},decryptBlock:function(e,t){var r=e[t+1];e[t+1]=e[t+3],e[t+3]=r,this._doCryptBlock(e,t,this._invKeySchedule,f,c,u,d,o),r=e[t+1],e[t+1]=e[t+3],e[t+3]=r},_doCryptBlock:function(e,t,r,n,i,o,a,s){for(var h=this._nRounds,l=e[t]^r[0],f=e[t+1]^r[1],c=e[t+2]^r[2],u=e[t+3]^r[3],d=4,p=1;p<h;p++){var _=n[l>>>24]^i[f>>>16&255]^o[c>>>8&255]^a[255&u]^r[d++],g=n[f>>>24]^i[c>>>16&255]^o[u>>>8&255]^a[255&l]^r[d++],v=n[c>>>24]^i[u>>>16&255]^o[l>>>8&255]^a[255&f]^r[d++],w=n[u>>>24]^i[l>>>16&255]^o[f>>>8&255]^a[255&c]^r[d++];l=_,f=g,c=v,u=w}_=(s[l>>>24]<<24|s[f>>>16&255]<<16|s[c>>>8&255]<<8|s[255&u])^r[d++],g=(s[f>>>24]<<24|s[c>>>16&255]<<16|s[u>>>8&255]<<8|s[255&l])^r[d++],v=(s[c>>>24]<<24|s[u>>>16&255]<<16|s[l>>>8&255]<<8|s[255&f])^r[d++],w=(s[u>>>24]<<24|s[l>>>16&255]<<16|s[f>>>8&255]<<8|s[255&c])^r[d++],e[t]=_,e[t+1]=g,e[t+2]=v,e[t+3]=w},keySize:8});e.AES=t._createHelper(_)}(),r.AES)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib,n=t.WordArray,i=t.BlockCipher,o=e.algo,a=[57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36,63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4],s=[14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32],h=[1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28],l=[{0:8421888,268435456:32768,536870912:8421378,805306368:2,1073741824:512,1342177280:8421890,1610612736:8389122,1879048192:8388608,2147483648:514,2415919104:8389120,2684354560:33280,2952790016:8421376,3221225472:32770,3489660928:8388610,3758096384:0,4026531840:33282,134217728:0,402653184:8421890,671088640:33282,939524096:32768,1207959552:8421888,1476395008:512,1744830464:8421378,2013265920:2,2281701376:8389120,2550136832:33280,2818572288:8421376,3087007744:8389122,3355443200:8388610,3623878656:32770,3892314112:514,4160749568:8388608,1:32768,268435457:2,536870913:8421888,805306369:8388608,1073741825:8421378,1342177281:33280,1610612737:512,1879048193:8389122,2147483649:8421890,2415919105:8421376,2684354561:8388610,2952790017:33282,3221225473:514,3489660929:8389120,3758096385:32770,4026531841:0,134217729:8421890,402653185:8421376,671088641:8388608,939524097:512,1207959553:32768,1476395009:8388610,1744830465:2,2013265921:33282,2281701377:32770,2550136833:8389122,2818572289:514,3087007745:8421888,3355443201:8389120,3623878657:0,3892314113:33280,4160749569:8421378},{0:1074282512,16777216:16384,33554432:524288,50331648:1074266128,67108864:1073741840,83886080:1074282496,100663296:1073758208,117440512:16,134217728:540672,150994944:1073758224,167772160:1073741824,184549376:540688,201326592:524304,218103808:0,234881024:16400,251658240:1074266112,8388608:1073758208,25165824:540688,41943040:16,58720256:1073758224,75497472:1074282512,92274688:1073741824,109051904:524288,125829120:1074266128,142606336:524304,159383552:0,176160768:16384,192937984:1074266112,209715200:1073741840,226492416:540672,243269632:1074282496,260046848:16400,268435456:0,285212672:1074266128,301989888:1073758224,318767104:1074282496,335544320:1074266112,352321536:16,369098752:540688,385875968:16384,402653184:16400,419430400:524288,436207616:524304,452984832:1073741840,469762048:540672,486539264:1073758208,503316480:1073741824,520093696:1074282512,276824064:540688,293601280:524288,310378496:1074266112,327155712:16384,343932928:1073758208,360710144:1074282512,377487360:16,394264576:1073741824,411041792:1074282496,427819008:1073741840,444596224:1073758224,461373440:524304,478150656:0,494927872:16400,511705088:1074266128,528482304:540672},{0:260,1048576:0,2097152:67109120,3145728:65796,4194304:65540,5242880:67108868,6291456:67174660,7340032:67174400,8388608:67108864,9437184:67174656,10485760:65792,11534336:67174404,12582912:67109124,13631488:65536,14680064:4,15728640:256,524288:67174656,1572864:67174404,2621440:0,3670016:67109120,4718592:67108868,5767168:65536,6815744:65540,7864320:260,8912896:4,9961472:256,11010048:67174400,12058624:65796,13107200:65792,14155776:67109124,15204352:67174660,16252928:67108864,16777216:67174656,17825792:65540,18874368:65536,19922944:67109120,20971520:256,22020096:67174660,23068672:67108868,24117248:0,25165824:67109124,26214400:67108864,27262976:4,28311552:65792,29360128:67174400,30408704:260,31457280:65796,32505856:67174404,17301504:67108864,18350080:260,19398656:67174656,20447232:0,21495808:65540,22544384:67109120,23592960:256,24641536:67174404,25690112:65536,26738688:67174660,27787264:65796,28835840:67108868,29884416:67109124,30932992:67174400,31981568:4,33030144:65792},{0:2151682048,65536:2147487808,131072:4198464,196608:2151677952,262144:0,327680:4198400,393216:2147483712,458752:4194368,524288:2147483648,589824:4194304,655360:64,720896:2147487744,786432:2151678016,851968:4160,917504:4096,983040:2151682112,32768:2147487808,98304:64,163840:2151678016,229376:2147487744,294912:4198400,360448:2151682112,425984:0,491520:2151677952,557056:4096,622592:2151682048,688128:4194304,753664:4160,819200:2147483648,884736:4194368,950272:4198464,1015808:2147483712,1048576:4194368,1114112:4198400,1179648:2147483712,1245184:0,1310720:4160,1376256:2151678016,1441792:2151682048,1507328:2147487808,1572864:2151682112,1638400:2147483648,1703936:2151677952,1769472:4198464,1835008:2147487744,1900544:4194304,1966080:64,2031616:4096,1081344:2151677952,1146880:2151682112,1212416:0,1277952:4198400,1343488:4194368,1409024:2147483648,1474560:2147487808,1540096:64,1605632:2147483712,1671168:4096,1736704:2147487744,1802240:2151678016,1867776:4160,1933312:2151682048,1998848:4194304,2064384:4198464},{0:128,4096:17039360,8192:262144,12288:536870912,16384:537133184,20480:16777344,24576:553648256,28672:262272,32768:16777216,36864:537133056,40960:536871040,45056:553910400,49152:553910272,53248:0,57344:17039488,61440:553648128,2048:17039488,6144:553648256,10240:128,14336:17039360,18432:262144,22528:537133184,26624:553910272,30720:536870912,34816:537133056,38912:0,43008:553910400,47104:16777344,51200:536871040,55296:553648128,59392:16777216,63488:262272,65536:262144,69632:128,73728:536870912,77824:553648256,81920:16777344,86016:553910272,90112:537133184,94208:16777216,98304:553910400,102400:553648128,106496:17039360,110592:537133056,114688:262272,118784:536871040,122880:0,126976:17039488,67584:553648256,71680:16777216,75776:17039360,79872:537133184,83968:536870912,88064:17039488,92160:128,96256:553910272,100352:262272,104448:553910400,108544:0,112640:553648128,116736:16777344,120832:262144,124928:537133056,129024:536871040},{0:268435464,256:8192,512:270532608,768:270540808,1024:268443648,1280:2097152,1536:2097160,1792:268435456,2048:0,2304:268443656,2560:2105344,2816:8,3072:270532616,3328:2105352,3584:8200,3840:270540800,128:270532608,384:270540808,640:8,896:2097152,1152:2105352,1408:268435464,1664:268443648,1920:8200,2176:2097160,2432:8192,2688:268443656,2944:270532616,3200:0,3456:270540800,3712:2105344,3968:268435456,4096:268443648,4352:270532616,4608:270540808,4864:8200,5120:2097152,5376:268435456,5632:268435464,5888:2105344,6144:2105352,6400:0,6656:8,6912:270532608,7168:8192,7424:268443656,7680:270540800,7936:2097160,4224:8,4480:2105344,4736:2097152,4992:268435464,5248:268443648,5504:8200,5760:270540808,6016:270532608,6272:270540800,6528:270532616,6784:8192,7040:2105352,7296:2097160,7552:0,7808:268435456,8064:268443656},{0:1048576,16:33555457,32:1024,48:1049601,64:34604033,80:0,96:1,112:34603009,128:33555456,144:1048577,160:33554433,176:34604032,192:34603008,208:1025,224:1049600,240:33554432,8:34603009,24:0,40:33555457,56:34604032,72:1048576,88:33554433,104:33554432,120:1025,136:1049601,152:33555456,168:34603008,184:1048577,200:1024,216:34604033,232:1,248:1049600,256:33554432,272:1048576,288:33555457,304:34603009,320:1048577,336:33555456,352:34604032,368:1049601,384:1025,400:34604033,416:1049600,432:1,448:0,464:34603008,480:33554433,496:1024,264:1049600,280:33555457,296:34603009,312:1,328:33554432,344:1048576,360:1025,376:34604032,392:33554433,408:34603008,424:0,440:34604033,456:1049601,472:1024,488:33555456,504:1048577},{0:134219808,1:131072,2:134217728,3:32,4:131104,5:134350880,6:134350848,7:2048,8:134348800,9:134219776,10:133120,11:134348832,12:2080,13:0,14:134217760,15:133152,2147483648:2048,2147483649:134350880,2147483650:134219808,2147483651:134217728,2147483652:134348800,2147483653:133120,2147483654:133152,2147483655:32,2147483656:134217760,2147483657:2080,2147483658:131104,2147483659:134350848,2147483660:0,2147483661:134348832,2147483662:134219776,2147483663:131072,16:133152,17:134350848,18:32,19:2048,20:134219776,21:134217760,22:134348832,23:131072,24:0,25:131104,26:134348800,27:134219808,28:134350880,29:133120,30:2080,31:134217728,2147483664:131072,2147483665:2048,2147483666:134348832,2147483667:133152,2147483668:32,2147483669:134348800,2147483670:134217728,2147483671:134219808,2147483672:134350880,2147483673:134217760,2147483674:134219776,2147483675:0,2147483676:133120,2147483677:2080,2147483678:131104,2147483679:134350848}],f=[4160749569,528482304,33030144,2064384,129024,8064,504,2147483679],c=o.DES=i.extend({_doReset:function(){for(var e=this._key.words,t=[],r=0;r<56;r++){var n=a[r]-1;t[r]=e[n>>>5]>>>31-n%32&1}for(var i=this._subKeys=[],o=0;o<16;o++){var l=i[o]=[],f=h[o];for(r=0;r<24;r++)l[r/6|0]|=t[(s[r]-1+f)%28]<<31-r%6,l[4+(r/6|0)]|=t[28+(s[r+24]-1+f)%28]<<31-r%6;for(l[0]=l[0]<<1|l[0]>>>31,r=1;r<7;r++)l[r]=l[r]>>>4*(r-1)+3;l[7]=l[7]<<5|l[7]>>>27}var c=this._invSubKeys=[];for(r=0;r<16;r++)c[r]=i[15-r]},encryptBlock:function(e,t){this._doCryptBlock(e,t,this._subKeys)},decryptBlock:function(e,t){this._doCryptBlock(e,t,this._invSubKeys)},_doCryptBlock:function(e,t,r){this._lBlock=e[t],this._rBlock=e[t+1],u.call(this,4,252645135),u.call(this,16,65535),d.call(this,2,858993459),d.call(this,8,16711935),u.call(this,1,1431655765);for(var n=0;n<16;n++){for(var i=r[n],o=this._lBlock,a=this._rBlock,s=0,h=0;h<8;h++)s|=l[h][((a^i[h])&f[h])>>>0];this._lBlock=a,this._rBlock=o^s}var c=this._lBlock;this._lBlock=this._rBlock,this._rBlock=c,u.call(this,1,1431655765),d.call(this,8,16711935),d.call(this,2,858993459),u.call(this,16,65535),u.call(this,4,252645135),e[t]=this._lBlock,e[t+1]=this._rBlock},keySize:2,ivSize:2,blockSize:2});function u(e,t){var r=(this._lBlock>>>e^this._rBlock)&t;this._rBlock^=r,this._lBlock^=r<<e}function d(e,t){var r=(this._rBlock>>>e^this._lBlock)&t;this._lBlock^=r,this._rBlock^=r<<e}e.DES=i._createHelper(c);var p=o.TripleDES=i.extend({_doReset:function(){var e=this._key.words;this._des1=c.createEncryptor(n.create(e.slice(0,2))),this._des2=c.createEncryptor(n.create(e.slice(2,4))),this._des3=c.createEncryptor(n.create(e.slice(4,6)))},encryptBlock:function(e,t){this._des1.encryptBlock(e,t),this._des2.decryptBlock(e,t),this._des3.encryptBlock(e,t)},decryptBlock:function(e,t){this._des3.decryptBlock(e,t),this._des2.encryptBlock(e,t),this._des1.decryptBlock(e,t)},keySize:6,ivSize:2,blockSize:2});e.TripleDES=i._createHelper(p)}(),r.TripleDES)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.StreamCipher,n=e.algo,i=n.RC4=t.extend({_doReset:function(){for(var e=this._key,t=e.words,r=e.sigBytes,n=this._S=[],i=0;i<256;i++)n[i]=i;i=0;for(var o=0;i<256;i++){var a=i%r,s=t[a>>>2]>>>24-a%4*8&255;o=(o+n[i]+s)%256;var h=n[i];n[i]=n[o],n[o]=h}this._i=this._j=0},_doProcessBlock:function(e,t){e[t]^=o.call(this)},keySize:8,ivSize:0});function o(){for(var e=this._S,t=this._i,r=this._j,n=0,i=0;i<4;i++){r=(r+e[t=(t+1)%256])%256;var o=e[t];e[t]=e[r],e[r]=o,n|=e[(e[t]+e[r])%256]<<24-8*i}return this._i=t,this._j=r,n}e.RC4=t._createHelper(i);var a=n.RC4Drop=i.extend({cfg:i.cfg.extend({drop:192}),_doReset:function(){i._doReset.call(this);for(var e=this.cfg.drop;e>0;e--)o.call(this)}});e.RC4Drop=t._createHelper(a)}(),r.RC4)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.StreamCipher,n=e.algo,i=[],o=[],a=[],s=n.Rabbit=t.extend({_doReset:function(){for(var e=this._key.words,t=this.cfg.iv,r=0;r<4;r++)e[r]=16711935&(e[r]<<8|e[r]>>>24)|4278255360&(e[r]<<24|e[r]>>>8);var n=this._X=[e[0],e[3]<<16|e[2]>>>16,e[1],e[0]<<16|e[3]>>>16,e[2],e[1]<<16|e[0]>>>16,e[3],e[2]<<16|e[1]>>>16],i=this._C=[e[2]<<16|e[2]>>>16,4294901760&e[0]|65535&e[1],e[3]<<16|e[3]>>>16,4294901760&e[1]|65535&e[2],e[0]<<16|e[0]>>>16,4294901760&e[2]|65535&e[3],e[1]<<16|e[1]>>>16,4294901760&e[3]|65535&e[0]];for(this._b=0,r=0;r<4;r++)h.call(this);for(r=0;r<8;r++)i[r]^=n[r+4&7];if(t){var o=t.words,a=o[0],s=o[1],l=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),f=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),c=l>>>16|4294901760&f,u=f<<16|65535&l;for(i[0]^=l,i[1]^=c,i[2]^=f,i[3]^=u,i[4]^=l,i[5]^=c,i[6]^=f,i[7]^=u,r=0;r<4;r++)h.call(this)}},_doProcessBlock:function(e,t){var r=this._X;h.call(this),i[0]=r[0]^r[5]>>>16^r[3]<<16,i[1]=r[2]^r[7]>>>16^r[5]<<16,i[2]=r[4]^r[1]>>>16^r[7]<<16,i[3]=r[6]^r[3]>>>16^r[1]<<16;for(var n=0;n<4;n++)i[n]=16711935&(i[n]<<8|i[n]>>>24)|4278255360&(i[n]<<24|i[n]>>>8),e[t+n]^=i[n]},blockSize:4,ivSize:2});function h(){for(var e=this._X,t=this._C,r=0;r<8;r++)o[r]=t[r];for(t[0]=t[0]+1295307597+this._b|0,t[1]=t[1]+3545052371+(t[0]>>>0<o[0]>>>0?1:0)|0,t[2]=t[2]+886263092+(t[1]>>>0<o[1]>>>0?1:0)|0,t[3]=t[3]+1295307597+(t[2]>>>0<o[2]>>>0?1:0)|0,t[4]=t[4]+3545052371+(t[3]>>>0<o[3]>>>0?1:0)|0,t[5]=t[5]+886263092+(t[4]>>>0<o[4]>>>0?1:0)|0,t[6]=t[6]+1295307597+(t[5]>>>0<o[5]>>>0?1:0)|0,t[7]=t[7]+3545052371+(t[6]>>>0<o[6]>>>0?1:0)|0,this._b=t[7]>>>0<o[7]>>>0?1:0,r=0;r<8;r++){var n=e[r]+t[r],i=65535&n,s=n>>>16,h=((i*i>>>17)+i*s>>>15)+s*s,l=((4294901760&n)*n|0)+((65535&n)*n|0);a[r]=h^l}e[0]=a[0]+(a[7]<<16|a[7]>>>16)+(a[6]<<16|a[6]>>>16)|0,e[1]=a[1]+(a[0]<<8|a[0]>>>24)+a[7]|0,e[2]=a[2]+(a[1]<<16|a[1]>>>16)+(a[0]<<16|a[0]>>>16)|0,e[3]=a[3]+(a[2]<<8|a[2]>>>24)+a[1]|0,e[4]=a[4]+(a[3]<<16|a[3]>>>16)+(a[2]<<16|a[2]>>>16)|0,e[5]=a[5]+(a[4]<<8|a[4]>>>24)+a[3]|0,e[6]=a[6]+(a[5]<<16|a[5]>>>16)+(a[4]<<16|a[4]>>>16)|0,e[7]=a[7]+(a[6]<<8|a[6]>>>24)+a[5]|0}e.Rabbit=t._createHelper(s)}(),r.Rabbit)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.StreamCipher,n=e.algo,i=[],o=[],a=[],s=n.RabbitLegacy=t.extend({_doReset:function(){var e=this._key.words,t=this.cfg.iv,r=this._X=[e[0],e[3]<<16|e[2]>>>16,e[1],e[0]<<16|e[3]>>>16,e[2],e[1]<<16|e[0]>>>16,e[3],e[2]<<16|e[1]>>>16],n=this._C=[e[2]<<16|e[2]>>>16,4294901760&e[0]|65535&e[1],e[3]<<16|e[3]>>>16,4294901760&e[1]|65535&e[2],e[0]<<16|e[0]>>>16,4294901760&e[2]|65535&e[3],e[1]<<16|e[1]>>>16,4294901760&e[3]|65535&e[0]];this._b=0;for(var i=0;i<4;i++)h.call(this);for(i=0;i<8;i++)n[i]^=r[i+4&7];if(t){var o=t.words,a=o[0],s=o[1],l=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),f=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),c=l>>>16|4294901760&f,u=f<<16|65535&l;for(n[0]^=l,n[1]^=c,n[2]^=f,n[3]^=u,n[4]^=l,n[5]^=c,n[6]^=f,n[7]^=u,i=0;i<4;i++)h.call(this)}},_doProcessBlock:function(e,t){var r=this._X;h.call(this),i[0]=r[0]^r[5]>>>16^r[3]<<16,i[1]=r[2]^r[7]>>>16^r[5]<<16,i[2]=r[4]^r[1]>>>16^r[7]<<16,i[3]=r[6]^r[3]>>>16^r[1]<<16;for(var n=0;n<4;n++)i[n]=16711935&(i[n]<<8|i[n]>>>24)|4278255360&(i[n]<<24|i[n]>>>8),e[t+n]^=i[n]},blockSize:4,ivSize:2});function h(){for(var e=this._X,t=this._C,r=0;r<8;r++)o[r]=t[r];for(t[0]=t[0]+1295307597+this._b|0,t[1]=t[1]+3545052371+(t[0]>>>0<o[0]>>>0?1:0)|0,t[2]=t[2]+886263092+(t[1]>>>0<o[1]>>>0?1:0)|0,t[3]=t[3]+1295307597+(t[2]>>>0<o[2]>>>0?1:0)|0,t[4]=t[4]+3545052371+(t[3]>>>0<o[3]>>>0?1:0)|0,t[5]=t[5]+886263092+(t[4]>>>0<o[4]>>>0?1:0)|0,t[6]=t[6]+1295307597+(t[5]>>>0<o[5]>>>0?1:0)|0,t[7]=t[7]+3545052371+(t[6]>>>0<o[6]>>>0?1:0)|0,this._b=t[7]>>>0<o[7]>>>0?1:0,r=0;r<8;r++){var n=e[r]+t[r],i=65535&n,s=n>>>16,h=((i*i>>>17)+i*s>>>15)+s*s,l=((4294901760&n)*n|0)+((65535&n)*n|0);a[r]=h^l}e[0]=a[0]+(a[7]<<16|a[7]>>>16)+(a[6]<<16|a[6]>>>16)|0,e[1]=a[1]+(a[0]<<8|a[0]>>>24)+a[7]|0,e[2]=a[2]+(a[1]<<16|a[1]>>>16)+(a[0]<<16|a[0]>>>16)|0,e[3]=a[3]+(a[2]<<8|a[2]>>>24)+a[1]|0,e[4]=a[4]+(a[3]<<16|a[3]>>>16)+(a[2]<<16|a[2]>>>16)|0,e[5]=a[5]+(a[4]<<8|a[4]>>>24)+a[3]|0,e[6]=a[6]+(a[5]<<16|a[5]>>>16)+(a[4]<<16|a[4]>>>16)|0,e[7]=a[7]+(a[6]<<8|a[6]>>>24)+a[5]|0}e.RabbitLegacy=t._createHelper(s)}(),r.RabbitLegacy)}),Q(function(e,t){e.exports=ee}));function re(){throw new Error("setTimeout has not been defined")}function ne(){throw new Error("clearTimeout has not been defined")}var ie=re,oe=ne;function ae(e){if(ie===setTimeout)return setTimeout(e,0);if((ie===re||!ie)&&setTimeout)return ie=setTimeout,setTimeout(e,0);try{return ie(e,0)}catch(t){try{return ie.call(null,e,0)}catch(t){return ie.call(this,e,0)}}}"function"==typeof e.setTimeout&&(ie=setTimeout),"function"==typeof e.clearTimeout&&(oe=clearTimeout);var se,he=[],le=!1,fe=-1;function ce(){le&&se&&(le=!1,se.length?he=se.concat(he):fe=-1,he.length&&ue())}function ue(){if(!le){var e=ae(ce);le=!0;for(var t=he.length;t;){for(se=he,he=[];++fe<t;)se&&se[fe].run();fe=-1,t=he.length}se=null,le=!1,function(e){if(oe===clearTimeout)return clearTimeout(e);if((oe===ne||!oe)&&clearTimeout)return oe=clearTimeout,clearTimeout(e);try{oe(e)}catch(t){try{return oe.call(null,e)}catch(t){return oe.call(this,e)}}}(e)}}function de(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)t[r-1]=arguments[r];he.push(new pe(e,t)),1!==he.length||le||ae(ue)}function pe(e,t){this.fun=e,this.array=t}pe.prototype.run=function(){this.fun.apply(null,this.array)};var _e=e.performance||{};_e.now||_e.mozNow||_e.msNow||_e.oNow||_e.webkitNow;function ge(){}function ve(){ve.init.call(this)}function we(e){return void 0===e._maxListeners?ve.defaultMaxListeners:e._maxListeners}function be(e,t,r){if(t)e.call(r);else for(var n=e.length,i=Ae(e,n),o=0;o<n;++o)i[o].call(r)}function ye(e,t,r,n){if(t)e.call(r,n);else for(var i=e.length,o=Ae(e,i),a=0;a<i;++a)o[a].call(r,n)}function me(e,t,r,n,i){if(t)e.call(r,n,i);else for(var o=e.length,a=Ae(e,o),s=0;s<o;++s)a[s].call(r,n,i)}function ke(e,t,r,n,i,o){if(t)e.call(r,n,i,o);else for(var a=e.length,s=Ae(e,a),h=0;h<a;++h)s[h].call(r,n,i,o)}function Ee(e,t,r,n){if(t)e.apply(r,n);else for(var i=e.length,o=Ae(e,i),a=0;a<i;++a)o[a].apply(r,n)}function Se(e,t,r,n){var i,o,a,s;if("function"!=typeof r)throw new TypeError('"listener" argument must be a function');if((o=e._events)?(o.newListener&&(e.emit("newListener",t,r.listener?r.listener:r),o=e._events),a=o[t]):(o=e._events=new ge,e._eventsCount=0),a){if("function"==typeof a?a=o[t]=n?[r,a]:[a,r]:n?a.unshift(r):a.push(r),!a.warned&&(i=we(e))&&i>0&&a.length>i){a.warned=!0;var h=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+t+" listeners added. Use emitter.setMaxListeners() to increase limit");h.name="MaxListenersExceededWarning",h.emitter=e,h.type=t,h.count=a.length,s=h,"function"==typeof console.warn?console.warn(s):console.log(s)}}else a=o[t]=r,++e._eventsCount;return e}function xe(e,t,r){var n=!1;function i(){e.removeListener(t,i),n||(n=!0,r.apply(e,arguments))}return i.listener=r,i}function Re(e){var t=this._events;if(t){var r=t[e];if("function"==typeof r)return 1;if(r)return r.length}return 0}function Ae(e,t){for(var r=new Array(t);t--;)r[t]=e[t];return r}ge.prototype=Object.create(null),ve.EventEmitter=ve,ve.usingDomains=!1,ve.prototype.domain=void 0,ve.prototype._events=void 0,ve.prototype._maxListeners=void 0,ve.defaultMaxListeners=10,ve.init=function(){this.domain=null,ve.usingDomains&&(void 0).active&&(void 0).Domain,this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=new ge,this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},ve.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||isNaN(e))throw new TypeError('"n" argument must be a positive number');return this._maxListeners=e,this},ve.prototype.getMaxListeners=function(){return we(this)},ve.prototype.emit=function(e){var t,r,n,i,o,a,s,h="error"===e;if(a=this._events)h=h&&null==a.error;else if(!h)return!1;if(s=this.domain,h){if(t=arguments[1],!s){if(t instanceof Error)throw t;var l=new Error('Uncaught, unspecified "error" event. ('+t+")");throw l.context=t,l}return t||(t=new Error('Uncaught, unspecified "error" event')),t.domainEmitter=this,t.domain=s,t.domainThrown=!1,s.emit("error",t),!1}if(!(r=a[e]))return!1;var f="function"==typeof r;switch(n=arguments.length){case 1:be(r,f,this);break;case 2:ye(r,f,this,arguments[1]);break;case 3:me(r,f,this,arguments[1],arguments[2]);break;case 4:ke(r,f,this,arguments[1],arguments[2],arguments[3]);break;default:for(i=new Array(n-1),o=1;o<n;o++)i[o-1]=arguments[o];Ee(r,f,this,i)}return!0},ve.prototype.addListener=function(e,t){return Se(this,e,t,!1)},ve.prototype.on=ve.prototype.addListener,ve.prototype.prependListener=function(e,t){return Se(this,e,t,!0)},ve.prototype.once=function(e,t){if("function"!=typeof t)throw new TypeError('"listener" argument must be a function');return this.on(e,xe(this,e,t)),this},ve.prototype.prependOnceListener=function(e,t){if("function"!=typeof t)throw new TypeError('"listener" argument must be a function');return this.prependListener(e,xe(this,e,t)),this},ve.prototype.removeListener=function(e,t){var r,n,i,o,a;if("function"!=typeof t)throw new TypeError('"listener" argument must be a function');if(!(n=this._events))return this;if(!(r=n[e]))return this;if(r===t||r.listener&&r.listener===t)0==--this._eventsCount?this._events=new ge:(delete n[e],n.removeListener&&this.emit("removeListener",e,r.listener||t));else if("function"!=typeof r){for(i=-1,o=r.length;o-- >0;)if(r[o]===t||r[o].listener&&r[o].listener===t){a=r[o].listener,i=o;break}if(i<0)return this;if(1===r.length){if(r[0]=void 0,0==--this._eventsCount)return this._events=new ge,this;delete n[e]}else!function(e,t){for(var r=t,n=r+1,i=e.length;n<i;r+=1,n+=1)e[r]=e[n];e.pop()}(r,i);n.removeListener&&this.emit("removeListener",e,a||t)}return this},ve.prototype.removeAllListeners=function(e){var t,r;if(!(r=this._events))return this;if(!r.removeListener)return 0===arguments.length?(this._events=new ge,this._eventsCount=0):r[e]&&(0==--this._eventsCount?this._events=new ge:delete r[e]),this;if(0===arguments.length){for(var n,i=Object.keys(r),o=0;o<i.length;++o)"removeListener"!==(n=i[o])&&this.removeAllListeners(n);return this.removeAllListeners("removeListener"),this._events=new ge,this._eventsCount=0,this}if("function"==typeof(t=r[e]))this.removeListener(e,t);else if(t)do{this.removeListener(e,t[t.length-1])}while(t[0]);return this},ve.prototype.listeners=function(e){var t,r=this._events;return r&&(t=r[e])?"function"==typeof t?[t.listener||t]:function(e){for(var t=new Array(e.length),r=0;r<t.length;++r)t[r]=e[r].listener||e[r];return t}(t):[]},ve.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):Re.call(e,t)},ve.prototype.listenerCount=Re,ve.prototype.eventNames=function(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]};var Be="function"==typeof Object.create?function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:function(e,t){e.super_=t;var r=function(){};r.prototype=t.prototype,e.prototype=new r,e.prototype.constructor=e},ze=/%[sdj%]/g;function Le(e){if(!Ze(e)){for(var t=[],r=0;r<arguments.length;r++)t.push(De(arguments[r]));return t.join(" ")}r=1;for(var n=arguments,i=n.length,o=String(e).replace(ze,function(e){if("%%"===e)return"%";if(r>=i)return e;switch(e){case"%s":return String(n[r++]);case"%d":return Number(n[r++]);case"%j":try{return JSON.stringify(n[r++])}catch(e){return"[Circular]"}default:return e}}),a=n[r];r<i;a=n[++r])Ne(a)||!Ye(a)?o+=" "+a:o+=" "+De(a);return o}function Te(t,r){if(je(e.process))return function(){return Te(t,r).apply(this,arguments)};var n=!1;return function(){return n||(console.error(r),n=!0),t.apply(this,arguments)}}var Me,Ce={};function De(e,t){var r={seen:[],stylize:Pe};return arguments.length>=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),Fe(t)?r.showHidden=t:t&&function(e,t){if(!t||!Ye(t))return e;var r=Object.keys(t),n=r.length;for(;n--;)e[r[n]]=t[r[n]]}(r,t),je(r.showHidden)&&(r.showHidden=!1),je(r.depth)&&(r.depth=2),je(r.colors)&&(r.colors=!1),je(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=Ie),Oe(r,e,r.depth)}function Ie(e,t){var r=De.styles[t];return r?"["+De.colors[r][0]+"m"+e+"["+De.colors[r][1]+"m":e}function Pe(e,t){return e}function Oe(e,t,r){if(e.customInspect&&t&&qe(t.inspect)&&t.inspect!==De&&(!t.constructor||t.constructor.prototype!==t)){var n=t.inspect(r,e);return Ze(n)||(n=Oe(e,n,r)),n}var i=function(e,t){if(je(t))return e.stylize("undefined","undefined");if(Ze(t)){var r="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(r,"string")}if(n=t,"number"==typeof n)return e.stylize(""+t,"number");var n;if(Fe(t))return e.stylize(""+t,"boolean");if(Ne(t))return e.stylize("null","null")}(e,t);if(i)return i;var o=Object.keys(t),a=function(e){var t={};return e.forEach(function(e,r){t[e]=!0}),t}(o);if(e.showHidden&&(o=Object.getOwnPropertyNames(t)),Xe(t)&&(o.indexOf("message")>=0||o.indexOf("description")>=0))return Ue(t);if(0===o.length){if(qe(t)){var s=t.name?": "+t.name:"";return e.stylize("[Function"+s+"]","special")}if(We(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(Ke(t))return e.stylize(Date.prototype.toString.call(t),"date");if(Xe(t))return Ue(t)}var h,l,f="",c=!1,u=["{","}"];(h=t,Array.isArray(h)&&(c=!0,u=["[","]"]),qe(t))&&(f=" [Function"+(t.name?": "+t.name:"")+"]");return We(t)&&(f=" "+RegExp.prototype.toString.call(t)),Ke(t)&&(f=" "+Date.prototype.toUTCString.call(t)),Xe(t)&&(f=" "+Ue(t)),0!==o.length||c&&0!=t.length?r<0?We(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special"):(e.seen.push(t),l=c?function(e,t,r,n,i){for(var o=[],a=0,s=t.length;a<s;++a)Ge(t,String(a))?o.push(He(e,t,r,n,String(a),!0)):o.push("");return i.forEach(function(i){i.match(/^\d+$/)||o.push(He(e,t,r,n,i,!0))}),o}(e,t,r,a,o):o.map(function(n){return He(e,t,r,a,n,c)}),e.seen.pop(),function(e,t,r){if(e.reduce(function(e,t){return t.indexOf("\n"),e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return r[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+r[1];return r[0]+t+" "+e.join(", ")+" "+r[1]}(l,f,u)):u[0]+f+u[1]}function Ue(e){return"["+Error.prototype.toString.call(e)+"]"}function He(e,t,r,n,i,o){var a,s,h;if((h=Object.getOwnPropertyDescriptor(t,i)||{value:t[i]}).get?s=h.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):h.set&&(s=e.stylize("[Setter]","special")),Ge(n,i)||(a="["+i+"]"),s||(e.seen.indexOf(h.value)<0?(s=Ne(r)?Oe(e,h.value,null):Oe(e,h.value,r-1)).indexOf("\n")>-1&&(s=o?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n")):s=e.stylize("[Circular]","special")),je(a)){if(o&&i.match(/^\d+$/))return s;(a=JSON.stringify(""+i)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+s}function Fe(e){return"boolean"==typeof e}function Ne(e){return null===e}function Ze(e){return"string"==typeof e}function je(e){return void 0===e}function We(e){return Ye(e)&&"[object RegExp]"===Ve(e)}function Ye(e){return"object"==typeof e&&null!==e}function Ke(e){return Ye(e)&&"[object Date]"===Ve(e)}function Xe(e){return Ye(e)&&("[object Error]"===Ve(e)||e instanceof Error)}function qe(e){return"function"==typeof e}function Ve(e){return Object.prototype.toString.call(e)}function Ge(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function $e(){this.head=null,this.tail=null,this.length=0}De.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},De.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},$e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},$e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},$e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},$e.prototype.clear=function(){this.head=this.tail=null,this.length=0},$e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,r=""+t.data;t=t.next;)r+=e+t.data;return r},$e.prototype.concat=function(e){if(0===this.length)return p.alloc(0);if(1===this.length)return this.head.data;for(var t=p.allocUnsafe(e>>>0),r=this.head,n=0;r;)r.data.copy(t,n),n+=r.data.length,r=r.next;return t};var Je=p.isEncoding||function(e){switch(e&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function Qe(e){switch(this.encoding=(e||"utf8").toLowerCase().replace(/[-_]/,""),function(e){if(e&&!Je(e))throw new Error("Unknown encoding: "+e)}(e),this.encoding){case"utf8":this.surrogateSize=3;break;case"ucs2":case"utf16le":this.surrogateSize=2,this.detectIncompleteChar=tt;break;case"base64":this.surrogateSize=3,this.detectIncompleteChar=rt;break;default:return void(this.write=et)}this.charBuffer=new p(6),this.charReceived=0,this.charLength=0}function et(e){return e.toString(this.encoding)}function tt(e){this.charReceived=e.length%2,this.charLength=this.charReceived?2:0}function rt(e){this.charReceived=e.length%3,this.charLength=this.charReceived?3:0}Qe.prototype.write=function(e){for(var t="";this.charLength;){var r=e.length>=this.charLength-this.charReceived?this.charLength-this.charReceived:e.length;if(e.copy(this.charBuffer,this.charReceived,0,r),this.charReceived+=r,this.charReceived<this.charLength)return"";if(e=e.slice(r,e.length),!((i=(t=this.charBuffer.slice(0,this.charLength).toString(this.encoding)).charCodeAt(t.length-1))>=55296&&i<=56319)){if(this.charReceived=this.charLength=0,0===e.length)return t;break}this.charLength+=this.surrogateSize,t=""}this.detectIncompleteChar(e);var n=e.length;this.charLength&&(e.copy(this.charBuffer,0,e.length-this.charReceived,n),n-=this.charReceived);var i;n=(t+=e.toString(this.encoding,0,n)).length-1;if((i=t.charCodeAt(n))>=55296&&i<=56319){var o=this.surrogateSize;return this.charLength+=o,this.charReceived+=o,this.charBuffer.copy(this.charBuffer,o,0,o),e.copy(this.charBuffer,0,0,o),t.substring(0,n)}return t},Qe.prototype.detectIncompleteChar=function(e){for(var t=e.length>=3?3:e.length;t>0;t--){var r=e[e.length-t];if(1==t&&r>>5==6){this.charLength=2;break}if(t<=2&&r>>4==14){this.charLength=3;break}if(t<=3&&r>>3==30){this.charLength=4;break}}this.charReceived=t},Qe.prototype.end=function(e){var t="";if(e&&e.length&&(t=this.write(e)),this.charReceived){var r=this.charReceived,n=this.charBuffer,i=this.encoding;t+=n.slice(0,r).toString(i)}return t},ot.ReadableState=it;var nt=function(e){je(Me)&&(Me=""),e=e.toUpperCase(),Ce[e]||(new RegExp("\\b"+e+"\\b","i").test(Me)?Ce[e]=function(){var t=Le.apply(null,arguments);console.error("%s %d: %s",e,0,t)}:Ce[e]=function(){});return Ce[e]}("stream");function it(e,t){e=e||{},this.objectMode=!!e.objectMode,t instanceof Ct&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var r=e.highWaterMark,n=this.objectMode?16:16384;this.highWaterMark=r||0===r?r:n,this.highWaterMark=~~this.highWaterMark,this.buffer=new $e,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.ranOut=!1,this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(this.decoder=new Qe(e.encoding),this.encoding=e.encoding)}function ot(e){if(!(this instanceof ot))return new ot(e);this._readableState=new it(e,this),this.readable=!0,e&&"function"==typeof e.read&&(this._read=e.read),ve.call(this)}function at(e,t,r,n,i){var o=function(e,t){var r=null;$(t)||"string"==typeof t||null==t||e.objectMode||(r=new TypeError("Invalid non-string/buffer chunk"));return r}(t,r);if(o)e.emit("error",o);else if(null===r)t.reading=!1,function(e,t){if(t.ended)return;if(t.decoder){var r=t.decoder.end();r&&r.length&&(t.buffer.push(r),t.length+=t.objectMode?1:r.length)}t.ended=!0,lt(e)}(e,t);else if(t.objectMode||r&&r.length>0)if(t.ended&&!i){var a=new Error("stream.push() after EOF");e.emit("error",a)}else if(t.endEmitted&&i){var s=new Error("stream.unshift() after end event");e.emit("error",s)}else{var h;!t.decoder||i||n||(r=t.decoder.write(r),h=!t.objectMode&&0===r.length),i||(t.reading=!1),h||(t.flowing&&0===t.length&&!t.sync?(e.emit("data",r),e.read(0)):(t.length+=t.objectMode?1:r.length,i?t.buffer.unshift(r):t.buffer.push(r),t.needReadable&<(e))),function(e,t){t.readingMore||(t.readingMore=!0,de(ct,e,t))}(e,t)}else i||(t.reading=!1);return function(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}(t)}Be(ot,ve),ot.prototype.push=function(e,t){var r=this._readableState;return r.objectMode||"string"!=typeof e||(t=t||r.defaultEncoding)!==r.encoding&&(e=p.from(e,t),t=""),at(this,r,e,t,!1)},ot.prototype.unshift=function(e){return at(this,this._readableState,e,"",!0)},ot.prototype.isPaused=function(){return!1===this._readableState.flowing},ot.prototype.setEncoding=function(e){return this._readableState.decoder=new Qe(e),this._readableState.encoding=e,this};var st=8388608;function ht(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=st?e=st:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function lt(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(nt("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?de(ft,e):ft(e))}function ft(e){nt("emit readable"),e.emit("readable"),pt(e)}function ct(e,t){for(var r=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(nt("maybeReadMore read 0"),e.read(0),r!==t.length);)r=t.length;t.readingMore=!1}function ut(e){nt("readable nexttick read 0"),e.read(0)}function dt(e,t){t.reading||(nt("resume read 0"),e.read(0)),t.resumeScheduled=!1,t.awaitDrain=0,e.emit("resume"),pt(e),t.flowing&&!t.reading&&e.read(0)}function pt(e){var t=e._readableState;for(nt("flow",t.flowing);t.flowing&&null!==e.read(););}function _t(e,t){return 0===t.length?null:(t.objectMode?r=t.buffer.shift():!e||e>=t.length?(r=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):r=function(e,t,r){var n;e<t.head.data.length?(n=t.head.data.slice(0,e),t.head.data=t.head.data.slice(e)):n=e===t.head.data.length?t.shift():r?function(e,t){var r=t.head,n=1,i=r.data;e-=i.length;for(;r=r.next;){var o=r.data,a=e>o.length?o.length:e;if(a===o.length?i+=o:i+=o.slice(0,e),0===(e-=a)){a===o.length?(++n,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=o.slice(a));break}++n}return t.length-=n,i}(e,t):function(e,t){var r=p.allocUnsafe(e),n=t.head,i=1;n.data.copy(r),e-=n.data.length;for(;n=n.next;){var o=n.data,a=e>o.length?o.length:e;if(o.copy(r,r.length-e,0,a),0===(e-=a)){a===o.length?(++i,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=o.slice(a));break}++i}return t.length-=i,r}(e,t);return n}(e,t.buffer,t.decoder),r);var r}function gt(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,de(vt,t,e))}function vt(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function wt(e,t){for(var r=0,n=e.length;r<n;r++)if(e[r]===t)return r;return-1}function bt(){}function yt(e,t,r){this.chunk=e,this.encoding=t,this.callback=r,this.next=null}function mt(e,t){Object.defineProperty(this,"buffer",{get:Te(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.")}),e=e||{},this.objectMode=!!e.objectMode,t instanceof Ct&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var r=e.highWaterMark,n=this.objectMode?16:16384;this.highWaterMark=r||0===r?r:n,this.highWaterMark=~~this.highWaterMark,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1;var i=!1===e.decodeStrings;this.decodeStrings=!i,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var r=e._writableState,n=r.sync,i=r.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(r),t)!function(e,t,r,n,i){--t.pendingcb,r?de(i,n):i(n);e._writableState.errorEmitted=!0,e.emit("error",n)}(e,r,n,t,i);else{var o=Rt(r);o||r.corked||r.bufferProcessing||!r.bufferedRequest||xt(e,r),n?de(St,e,r,o,i):St(e,r,o,i)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new zt(this)}function kt(e){if(!(this instanceof kt||this instanceof Ct))return new kt(e);this._writableState=new mt(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev)),ve.call(this)}function Et(e,t,r,n,i,o,a){t.writelen=n,t.writecb=a,t.writing=!0,t.sync=!0,r?e._writev(i,t.onwrite):e._write(i,o,t.onwrite),t.sync=!1}function St(e,t,r,n){r||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,n(),Bt(e,t)}function xt(e,t){t.bufferProcessing=!0;var r=t.bufferedRequest;if(e._writev&&r&&r.next){var n=t.bufferedRequestCount,i=new Array(n),o=t.corkedRequestsFree;o.entry=r;for(var a=0;r;)i[a]=r,r=r.next,a+=1;Et(e,t,!0,t.length,i,"",o.finish),t.pendingcb++,t.lastBufferedRequest=null,o.next?(t.corkedRequestsFree=o.next,o.next=null):t.corkedRequestsFree=new zt(t)}else{for(;r;){var s=r.chunk,h=r.encoding,l=r.callback;if(Et(e,t,!1,t.objectMode?1:s.length,s,h,l),r=r.next,t.writing)break}null===r&&(t.lastBufferedRequest=null)}t.bufferedRequestCount=0,t.bufferedRequest=r,t.bufferProcessing=!1}function Rt(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function At(e,t){t.prefinished||(t.prefinished=!0,e.emit("prefinish"))}function Bt(e,t){var r=Rt(t);return r&&(0===t.pendingcb?(At(e,t),t.finished=!0,e.emit("finish")):At(e,t)),r}function zt(e){var t=this;this.next=null,this.entry=null,this.finish=function(r){var n=t.entry;for(t.entry=null;n;){var i=n.callback;e.pendingcb--,i(r),n=n.next}e.corkedRequestsFree?e.corkedRequestsFree.next=t:e.corkedRequestsFree=t}}ot.prototype.read=function(e){nt("read",e),e=parseInt(e,10);var t=this._readableState,r=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return nt("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?gt(this):lt(this),null;if(0===(e=ht(e,t))&&t.ended)return 0===t.length&>(this),null;var n,i=t.needReadable;return nt("need readable",i),(0===t.length||t.length-e<t.highWaterMark)&&nt("length less than watermark",i=!0),t.ended||t.reading?nt("reading or ended",i=!1):i&&(nt("do read"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=ht(r,t))),null===(n=e>0?_t(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),r!==e&&t.ended&>(this)),null!==n&&this.emit("data",n),n},ot.prototype._read=function(e){this.emit("error",new Error("not implemented"))},ot.prototype.pipe=function(e,t){var r=this,n=this._readableState;switch(n.pipesCount){case 0:n.pipes=e;break;case 1:n.pipes=[n.pipes,e];break;default:n.pipes.push(e)}n.pipesCount+=1,nt("pipe count=%d opts=%j",n.pipesCount,t);var i=!t||!1!==t.end?a:l;function o(e){nt("onunpipe"),e===r&&l()}function a(){nt("onend"),e.end()}n.endEmitted?de(i):r.once("end",i),e.on("unpipe",o);var s=function(e){return function(){var t=e._readableState;nt("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&e.listeners("data").length&&(t.flowing=!0,pt(e))}}(r);e.on("drain",s);var h=!1;function l(){nt("cleanup"),e.removeListener("close",d),e.removeListener("finish",p),e.removeListener("drain",s),e.removeListener("error",u),e.removeListener("unpipe",o),r.removeListener("end",a),r.removeListener("end",l),r.removeListener("data",c),h=!0,!n.awaitDrain||e._writableState&&!e._writableState.needDrain||s()}var f=!1;function c(t){nt("ondata"),f=!1,!1!==e.write(t)||f||((1===n.pipesCount&&n.pipes===e||n.pipesCount>1&&-1!==wt(n.pipes,e))&&!h&&(nt("false write response, pause",r._readableState.awaitDrain),r._readableState.awaitDrain++,f=!0),r.pause())}function u(t){var r;nt("onerror",t),_(),e.removeListener("error",u),0===(r="error",e.listeners(r).length)&&e.emit("error",t)}function d(){e.removeListener("finish",p),_()}function p(){nt("onfinish"),e.removeListener("close",d),_()}function _(){nt("unpipe"),r.unpipe(e)}return r.on("data",c),function(e,t,r){if("function"==typeof e.prependListener)return e.prependListener(t,r);e._events&&e._events[t]?Array.isArray(e._events[t])?e._events[t].unshift(r):e._events[t]=[r,e._events[t]]:e.on(t,r)}(e,"error",u),e.once("close",d),e.once("finish",p),e.emit("pipe",r),n.flowing||(nt("pipe resume"),r.resume()),e},ot.prototype.unpipe=function(e){var t=this._readableState;if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this),this);if(!e){var r=t.pipes,n=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i<n;i++)r[i].emit("unpipe",this);return this}var o=wt(t.pipes,e);return-1===o?this:(t.pipes.splice(o,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this),this)},ot.prototype.on=function(e,t){var r=ve.prototype.on.call(this,e,t);if("data"===e)!1!==this._readableState.flowing&&this.resume();else if("readable"===e){var n=this._readableState;n.endEmitted||n.readableListening||(n.readableListening=n.needReadable=!0,n.emittedReadable=!1,n.reading?n.length&<(this):de(ut,this))}return r},ot.prototype.addListener=ot.prototype.on,ot.prototype.resume=function(){var e=this._readableState;return e.flowing||(nt("resume"),e.flowing=!0,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,de(dt,e,t))}(this,e)),this},ot.prototype.pause=function(){return nt("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(nt("pause"),this._readableState.flowing=!1,this.emit("pause")),this},ot.prototype.wrap=function(e){var t=this._readableState,r=!1,n=this;for(var i in e.on("end",function(){if(nt("wrapped end"),t.decoder&&!t.ended){var e=t.decoder.end();e&&e.length&&n.push(e)}n.push(null)}),e.on("data",function(i){(nt("wrapped data"),t.decoder&&(i=t.decoder.write(i)),t.objectMode&&null==i)||(t.objectMode||i&&i.length)&&(n.push(i)||(r=!0,e.pause()))}),e)void 0===this[i]&&"function"==typeof e[i]&&(this[i]=function(t){return function(){return e[t].apply(e,arguments)}}(i));return function(e,t){for(var r=0,n=e.length;r<n;r++)t(e[r],r)}(["error","close","destroy","pause","resume"],function(t){e.on(t,n.emit.bind(n,t))}),n._read=function(t){nt("wrapped _read",t),r&&(r=!1,e.resume())},n},ot._fromList=_t,kt.WritableState=mt,Be(kt,ve),mt.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},kt.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},kt.prototype.write=function(e,t,r){var n=this._writableState,i=!1;return"function"==typeof t&&(r=t,t=null),p.isBuffer(e)?t="buffer":t||(t=n.defaultEncoding),"function"!=typeof r&&(r=bt),n.ended?function(e,t){var r=new Error("write after end");e.emit("error",r),de(t,r)}(this,r):function(e,t,r,n){var i=!0,o=!1;return null===r?o=new TypeError("May not write null values to stream"):p.isBuffer(r)||"string"==typeof r||void 0===r||t.objectMode||(o=new TypeError("Invalid non-string/buffer chunk")),o&&(e.emit("error",o),de(n,o),i=!1),i}(this,n,e,r)&&(n.pendingcb++,i=function(e,t,r,n,i){r=function(e,t,r){return e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=p.from(t,r)),t}(t,r,n),p.isBuffer(r)&&(n="buffer");var o=t.objectMode?1:r.length;t.length+=o;var a=t.length<t.highWaterMark;a||(t.needDrain=!0);if(t.writing||t.corked){var s=t.lastBufferedRequest;t.lastBufferedRequest=new yt(r,n,i),s?s.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else Et(e,t,!1,o,r,n,i);return a}(this,n,e,t,r)),i},kt.prototype.cork=function(){this._writableState.corked++},kt.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.finished||e.bufferProcessing||!e.bufferedRequest||xt(this,e))},kt.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},kt.prototype._write=function(e,t,r){r(new Error("not implemented"))},kt.prototype._writev=null,kt.prototype.end=function(e,t,r){var n=this._writableState;"function"==typeof e?(r=e,e=null,t=null):"function"==typeof t&&(r=t,t=null),null!=e&&this.write(e,t),n.corked&&(n.corked=1,this.uncork()),n.ending||n.finished||function(e,t,r){t.ending=!0,Bt(e,t),r&&(t.finished?de(r):e.once("finish",r));t.ended=!0,e.writable=!1}(this,n,r)},Be(Ct,ot);for(var Lt=Object.keys(kt.prototype),Tt=0;Tt<Lt.length;Tt++){var Mt=Lt[Tt];Ct.prototype[Mt]||(Ct.prototype[Mt]=kt.prototype[Mt])}function Ct(e){if(!(this instanceof Ct))return new Ct(e);ot.call(this,e),kt.call(this,e),e&&!1===e.readable&&(this.readable=!1),e&&!1===e.writable&&(this.writable=!1),this.allowHalfOpen=!0,e&&!1===e.allowHalfOpen&&(this.allowHalfOpen=!1),this.once("end",Dt)}function Dt(){this.allowHalfOpen||this._writableState.ended||de(It,this)}function It(e){e.end()}function Pt(e){this.afterTransform=function(t,r){return function(e,t,r){var n=e._transformState;n.transforming=!1;var i=n.writecb;if(!i)return e.emit("error",new Error("no writecb in Transform class"));n.writechunk=null,n.writecb=null,null!=r&&e.push(r);i(t);var o=e._readableState;o.reading=!1,(o.needReadable||o.length<o.highWaterMark)&&e._read(o.highWaterMark)}(e,t,r)},this.needTransform=!1,this.transforming=!1,this.writecb=null,this.writechunk=null,this.writeencoding=null}function Ot(e){if(!(this instanceof Ot))return new Ot(e);Ct.call(this,e),this._transformState=new Pt(this);var t=this;this._readableState.needReadable=!0,this._readableState.sync=!1,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.once("prefinish",function(){"function"==typeof this._flush?this._flush(function(e){Ut(t,e)}):Ut(t)})}function Ut(e,t){if(t)return e.emit("error",t);var r=e._writableState,n=e._transformState;if(r.length)throw new Error("Calling transform done when ws.length != 0");if(n.transforming)throw new Error("Calling transform done when still transforming");return e.push(null)}function Ht(e){if(!(this instanceof Ht))return new Ht(e);Ot.call(this,e)}function Ft(){ve.call(this)}Be(Ot,Ct),Ot.prototype.push=function(e,t){return this._transformState.needTransform=!1,Ct.prototype.push.call(this,e,t)},Ot.prototype._transform=function(e,t,r){throw new Error("Not implemented")},Ot.prototype._write=function(e,t,r){var n=this._transformState;if(n.writecb=r,n.writechunk=e,n.writeencoding=t,!n.transforming){var i=this._readableState;(n.needTransform||i.needReadable||i.length<i.highWaterMark)&&this._read(i.highWaterMark)}},Ot.prototype._read=function(e){var t=this._transformState;null!==t.writechunk&&t.writecb&&!t.transforming?(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform)):t.needTransform=!0},Be(Ht,Ot),Ht.prototype._transform=function(e,t,r){r(null,e)},Be(Ft,ve),Ft.Readable=ot,Ft.Writable=kt,Ft.Duplex=Ct,Ft.Transform=Ot,Ft.PassThrough=Ht,Ft.Stream=Ft,Ft.prototype.pipe=function(e,t){var r=this;function n(t){e.writable&&!1===e.write(t)&&r.pause&&r.pause()}function i(){r.readable&&r.resume&&r.resume()}r.on("data",n),e.on("drain",i),e._isStdio||t&&!1===t.end||(r.on("end",a),r.on("close",s));var o=!1;function a(){o||(o=!0,e.end())}function s(){o||(o=!0,"function"==typeof e.destroy&&e.destroy())}function h(e){if(l(),0===ve.listenerCount(this,"error"))throw e}function l(){r.removeListener("data",n),e.removeListener("drain",i),r.removeListener("end",a),r.removeListener("close",s),r.removeListener("error",h),e.removeListener("error",h),r.removeListener("end",l),r.removeListener("close",l),e.removeListener("close",l)}return r.on("error",h),e.on("error",h),r.on("end",l),r.on("close",l),e.on("close",l),e.emit("pipe",r),e};var Nt={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"};function Zt(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}function jt(e,t,r,n,i){if(t.subarray&&e.subarray)e.set(t.subarray(r,r+n),i);else for(var o=0;o<n;o++)e[i+o]=t[r+o]}var Wt=Uint8Array,Yt=Uint16Array,Kt=Int32Array,Xt=4,qt=0,Vt=1,Gt=2;function $t(e){for(var t=e.length;--t>=0;)e[t]=0}var Jt=0,Qt=1,er=2,tr=29,rr=256,nr=rr+1+tr,ir=30,or=19,ar=2*nr+1,sr=15,hr=16,lr=7,fr=256,cr=16,ur=17,dr=18,pr=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],_r=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],gr=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],vr=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],wr=new Array(2*(nr+2));$t(wr);var br=new Array(2*ir);$t(br);var yr=new Array(512);$t(yr);var mr=new Array(256);$t(mr);var kr=new Array(tr);$t(kr);var Er,Sr,xr,Rr=new Array(ir);function Ar(e,t,r,n,i){this.static_tree=e,this.extra_bits=t,this.extra_base=r,this.elems=n,this.max_length=i,this.has_stree=e&&e.length}function Br(e,t){this.dyn_tree=e,this.max_code=0,this.stat_desc=t}function zr(e){return e<256?yr[e]:yr[256+(e>>>7)]}function Lr(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function Tr(e,t,r){e.bi_valid>hr-r?(e.bi_buf|=t<<e.bi_valid&65535,Lr(e,e.bi_buf),e.bi_buf=t>>hr-e.bi_valid,e.bi_valid+=r-hr):(e.bi_buf|=t<<e.bi_valid&65535,e.bi_valid+=r)}function Mr(e,t,r){Tr(e,r[2*t],r[2*t+1])}function Cr(e,t){var r=0;do{r|=1&e,e>>>=1,r<<=1}while(--t>0);return r>>>1}function Dr(e,t,r){var n,i,o=new Array(sr+1),a=0;for(n=1;n<=sr;n++)o[n]=a=a+r[n-1]<<1;for(i=0;i<=t;i++){var s=e[2*i+1];0!==s&&(e[2*i]=Cr(o[s]++,s))}}function Ir(e){var t;for(t=0;t<nr;t++)e.dyn_ltree[2*t]=0;for(t=0;t<ir;t++)e.dyn_dtree[2*t]=0;for(t=0;t<or;t++)e.bl_tree[2*t]=0;e.dyn_ltree[2*fr]=1,e.opt_len=e.static_len=0,e.last_lit=e.matches=0}function Pr(e){e.bi_valid>8?Lr(e,e.bi_buf):e.bi_valid>0&&(e.pending_buf[e.pending++]=e.bi_buf),e.bi_buf=0,e.bi_valid=0}function Or(e,t,r,n){var i=2*t,o=2*r;return e[i]<e[o]||e[i]===e[o]&&n[t]<=n[r]}function Ur(e,t,r){for(var n=e.heap[r],i=r<<1;i<=e.heap_len&&(i<e.heap_len&&Or(t,e.heap[i+1],e.heap[i],e.depth)&&i++,!Or(t,n,e.heap[i],e.depth));)e.heap[r]=e.heap[i],r=i,i<<=1;e.heap[r]=n}function Hr(e,t,r){var n,i,o,a,s=0;if(0!==e.last_lit)do{n=e.pending_buf[e.d_buf+2*s]<<8|e.pending_buf[e.d_buf+2*s+1],i=e.pending_buf[e.l_buf+s],s++,0===n?Mr(e,i,t):(Mr(e,(o=mr[i])+rr+1,t),0!==(a=pr[o])&&Tr(e,i-=kr[o],a),Mr(e,o=zr(--n),r),0!==(a=_r[o])&&Tr(e,n-=Rr[o],a))}while(s<e.last_lit);Mr(e,fr,t)}function Fr(e,t){var r,n,i,o=t.dyn_tree,a=t.stat_desc.static_tree,s=t.stat_desc.has_stree,h=t.stat_desc.elems,l=-1;for(e.heap_len=0,e.heap_max=ar,r=0;r<h;r++)0!==o[2*r]?(e.heap[++e.heap_len]=l=r,e.depth[r]=0):o[2*r+1]=0;for(;e.heap_len<2;)o[2*(i=e.heap[++e.heap_len]=l<2?++l:0)]=1,e.depth[i]=0,e.opt_len--,s&&(e.static_len-=a[2*i+1]);for(t.max_code=l,r=e.heap_len>>1;r>=1;r--)Ur(e,o,r);i=h;do{r=e.heap[1],e.heap[1]=e.heap[e.heap_len--],Ur(e,o,1),n=e.heap[1],e.heap[--e.heap_max]=r,e.heap[--e.heap_max]=n,o[2*i]=o[2*r]+o[2*n],e.depth[i]=(e.depth[r]>=e.depth[n]?e.depth[r]:e.depth[n])+1,o[2*r+1]=o[2*n+1]=i,e.heap[1]=i++,Ur(e,o,1)}while(e.heap_len>=2);e.heap[--e.heap_max]=e.heap[1],function(e,t){var r,n,i,o,a,s,h=t.dyn_tree,l=t.max_code,f=t.stat_desc.static_tree,c=t.stat_desc.has_stree,u=t.stat_desc.extra_bits,d=t.stat_desc.extra_base,p=t.stat_desc.max_length,_=0;for(o=0;o<=sr;o++)e.bl_count[o]=0;for(h[2*e.heap[e.heap_max]+1]=0,r=e.heap_max+1;r<ar;r++)(o=h[2*h[2*(n=e.heap[r])+1]+1]+1)>p&&(o=p,_++),h[2*n+1]=o,n>l||(e.bl_count[o]++,a=0,n>=d&&(a=u[n-d]),s=h[2*n],e.opt_len+=s*(o+a),c&&(e.static_len+=s*(f[2*n+1]+a)));if(0!==_){do{for(o=p-1;0===e.bl_count[o];)o--;e.bl_count[o]--,e.bl_count[o+1]+=2,e.bl_count[p]--,_-=2}while(_>0);for(o=p;0!==o;o--)for(n=e.bl_count[o];0!==n;)(i=e.heap[--r])>l||(h[2*i+1]!==o&&(e.opt_len+=(o-h[2*i+1])*h[2*i],h[2*i+1]=o),n--)}}(e,t),Dr(o,l,e.bl_count)}function Nr(e,t,r){var n,i,o=-1,a=t[1],s=0,h=7,l=4;for(0===a&&(h=138,l=3),t[2*(r+1)+1]=65535,n=0;n<=r;n++)i=a,a=t[2*(n+1)+1],++s<h&&i===a||(s<l?e.bl_tree[2*i]+=s:0!==i?(i!==o&&e.bl_tree[2*i]++,e.bl_tree[2*cr]++):s<=10?e.bl_tree[2*ur]++:e.bl_tree[2*dr]++,s=0,o=i,0===a?(h=138,l=3):i===a?(h=6,l=3):(h=7,l=4))}function Zr(e,t,r){var n,i,o=-1,a=t[1],s=0,h=7,l=4;for(0===a&&(h=138,l=3),n=0;n<=r;n++)if(i=a,a=t[2*(n+1)+1],!(++s<h&&i===a)){if(s<l)do{Mr(e,i,e.bl_tree)}while(0!=--s);else 0!==i?(i!==o&&(Mr(e,i,e.bl_tree),s--),Mr(e,cr,e.bl_tree),Tr(e,s-3,2)):s<=10?(Mr(e,ur,e.bl_tree),Tr(e,s-3,3)):(Mr(e,dr,e.bl_tree),Tr(e,s-11,7));s=0,o=i,0===a?(h=138,l=3):i===a?(h=6,l=3):(h=7,l=4)}}$t(Rr);var jr=!1;function Wr(e){jr||(!function(){var e,t,r,n,i,o=new Array(sr+1);for(r=0,n=0;n<tr-1;n++)for(kr[n]=r,e=0;e<1<<pr[n];e++)mr[r++]=n;for(mr[r-1]=n,i=0,n=0;n<16;n++)for(Rr[n]=i,e=0;e<1<<_r[n];e++)yr[i++]=n;for(i>>=7;n<ir;n++)for(Rr[n]=i<<7,e=0;e<1<<_r[n]-7;e++)yr[256+i++]=n;for(t=0;t<=sr;t++)o[t]=0;for(e=0;e<=143;)wr[2*e+1]=8,e++,o[8]++;for(;e<=255;)wr[2*e+1]=9,e++,o[9]++;for(;e<=279;)wr[2*e+1]=7,e++,o[7]++;for(;e<=287;)wr[2*e+1]=8,e++,o[8]++;for(Dr(wr,nr+1,o),e=0;e<ir;e++)br[2*e+1]=5,br[2*e]=Cr(e,5);Er=new Ar(wr,pr,rr+1,nr,sr),Sr=new Ar(br,_r,0,ir,sr),xr=new Ar(new Array(0),gr,0,or,lr)}(),jr=!0),e.l_desc=new Br(e.dyn_ltree,Er),e.d_desc=new Br(e.dyn_dtree,Sr),e.bl_desc=new Br(e.bl_tree,xr),e.bi_buf=0,e.bi_valid=0,Ir(e)}function Yr(e,t,r,n){Tr(e,(Jt<<1)+(n?1:0),3),function(e,t,r,n){Pr(e),n&&(Lr(e,r),Lr(e,~r)),jt(e.pending_buf,e.window,t,r,e.pending),e.pending+=r}(e,t,r,!0)}function Kr(e){Tr(e,Qt<<1,3),Mr(e,fr,wr),function(e){16===e.bi_valid?(Lr(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):e.bi_valid>=8&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}function Xr(e,t,r,n){var i,o,a=0;e.level>0?(e.strm.data_type===Gt&&(e.strm.data_type=function(e){var t,r=4093624447;for(t=0;t<=31;t++,r>>>=1)if(1&r&&0!==e.dyn_ltree[2*t])return qt;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return Vt;for(t=32;t<rr;t++)if(0!==e.dyn_ltree[2*t])return Vt;return qt}(e)),Fr(e,e.l_desc),Fr(e,e.d_desc),a=function(e){var t;for(Nr(e,e.dyn_ltree,e.l_desc.max_code),Nr(e,e.dyn_dtree,e.d_desc.max_code),Fr(e,e.bl_desc),t=or-1;t>=3&&0===e.bl_tree[2*vr[t]+1];t--);return e.opt_len+=3*(t+1)+5+5+4,t}(e),i=e.opt_len+3+7>>>3,(o=e.static_len+3+7>>>3)<=i&&(i=o)):i=o=r+5,r+4<=i&&-1!==t?Yr(e,t,r,n):e.strategy===Xt||o===i?(Tr(e,(Qt<<1)+(n?1:0),3),Hr(e,wr,br)):(Tr(e,(er<<1)+(n?1:0),3),function(e,t,r,n){var i;for(Tr(e,t-257,5),Tr(e,r-1,5),Tr(e,n-4,4),i=0;i<n;i++)Tr(e,e.bl_tree[2*vr[i]+1],3);Zr(e,e.dyn_ltree,t-1),Zr(e,e.dyn_dtree,r-1)}(e,e.l_desc.max_code+1,e.d_desc.max_code+1,a+1),Hr(e,e.dyn_ltree,e.dyn_dtree)),Ir(e),n&&Pr(e)}function qr(e,t,r){return e.pending_buf[e.d_buf+2*e.last_lit]=t>>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(mr[r]+rr+1)]++,e.dyn_dtree[2*zr(t)]++),e.last_lit===e.lit_bufsize-1}function Vr(e,t,r,n){for(var i=65535&e|0,o=e>>>16&65535|0,a=0;0!==r;){r-=a=r>2e3?2e3:r;do{o=o+(i=i+t[n++]|0)|0}while(--a);i%=65521,o%=65521}return i|o<<16|0}var Gr=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();function $r(e,t,r,n){var i=Gr,o=n+r;e^=-1;for(var a=n;a<o;a++)e=e>>>8^i[255&(e^t[a])];return-1^e}var Jr,Qr=0,en=1,tn=3,rn=4,nn=5,on=0,an=1,sn=-2,hn=-3,ln=-5,fn=-1,cn=1,un=2,dn=3,pn=4,_n=2,gn=8,vn=9,wn=286,bn=30,yn=19,mn=2*wn+1,kn=15,En=3,Sn=258,xn=Sn+En+1,Rn=32,An=42,Bn=69,zn=73,Ln=91,Tn=103,Mn=113,Cn=666,Dn=1,In=2,Pn=3,On=4,Un=3;function Hn(e,t){return e.msg=Nt[t],t}function Fn(e){return(e<<1)-(e>4?9:0)}function Nn(e){for(var t=e.length;--t>=0;)e[t]=0}function Zn(e){var t=e.state,r=t.pending;r>e.avail_out&&(r=e.avail_out),0!==r&&(jt(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function jn(e,t){Xr(e,e.block_start>=0?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,Zn(e.strm)}function Wn(e,t){e.pending_buf[e.pending++]=t}function Yn(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function Kn(e,t){var r,n,i=e.max_chain_length,o=e.strstart,a=e.prev_length,s=e.nice_match,h=e.strstart>e.w_size-xn?e.strstart-(e.w_size-xn):0,l=e.window,f=e.w_mask,c=e.prev,u=e.strstart+Sn,d=l[o+a-1],p=l[o+a];e.prev_length>=e.good_match&&(i>>=2),s>e.lookahead&&(s=e.lookahead);do{if(l[(r=t)+a]===p&&l[r+a-1]===d&&l[r]===l[o]&&l[++r]===l[o+1]){o+=2,r++;do{}while(l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&o<u);if(n=Sn-(u-o),o=u-Sn,n>a){if(e.match_start=t,a=n,n>=s)break;d=l[o+a-1],p=l[o+a]}}}while((t=c[t&f])>h&&0!=--i);return a<=e.lookahead?a:e.lookahead}function Xn(e){var t,r,n,i,o,a,s,h,l,f,c=e.w_size;do{if(i=e.window_size-e.lookahead-e.strstart,e.strstart>=c+(c-xn)){jt(e.window,e.window,c,c,0),e.match_start-=c,e.strstart-=c,e.block_start-=c,t=r=e.hash_size;do{n=e.head[--t],e.head[t]=n>=c?n-c:0}while(--r);t=r=c;do{n=e.prev[--t],e.prev[t]=n>=c?n-c:0}while(--r);i+=c}if(0===e.strm.avail_in)break;if(a=e.strm,s=e.window,h=e.strstart+e.lookahead,l=i,f=void 0,(f=a.avail_in)>l&&(f=l),r=0===f?0:(a.avail_in-=f,jt(s,a.input,a.next_in,f,h),1===a.state.wrap?a.adler=Vr(a.adler,s,f,h):2===a.state.wrap&&(a.adler=$r(a.adler,s,f,h)),a.next_in+=f,a.total_in+=f,f),e.lookahead+=r,e.lookahead+e.insert>=En)for(o=e.strstart-e.insert,e.ins_h=e.window[o],e.ins_h=(e.ins_h<<e.hash_shift^e.window[o+1])&e.hash_mask;e.insert&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[o+En-1])&e.hash_mask,e.prev[o&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=o,o++,e.insert--,!(e.lookahead+e.insert<En)););}while(e.lookahead<xn&&0!==e.strm.avail_in)}function qn(e,t){for(var r,n;;){if(e.lookahead<xn){if(Xn(e),e.lookahead<xn&&t===Qr)return Dn;if(0===e.lookahead)break}if(r=0,e.lookahead>=En&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+En-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),0!==r&&e.strstart-r<=e.w_size-xn&&(e.match_length=Kn(e,r)),e.match_length>=En)if(n=qr(e,e.strstart-e.match_start,e.match_length-En),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=En){e.match_length--;do{e.strstart++,e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+En-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart}while(0!=--e.match_length);e.strstart++}else e.strstart+=e.match_length,e.match_length=0,e.ins_h=e.window[e.strstart],e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+1])&e.hash_mask;else n=qr(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++;if(n&&(jn(e,!1),0===e.strm.avail_out))return Dn}return e.insert=e.strstart<En-1?e.strstart:En-1,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):e.last_lit&&(jn(e,!1),0===e.strm.avail_out)?Dn:In}function Vn(e,t){for(var r,n,i;;){if(e.lookahead<xn){if(Xn(e),e.lookahead<xn&&t===Qr)return Dn;if(0===e.lookahead)break}if(r=0,e.lookahead>=En&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+En-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),e.prev_length=e.match_length,e.prev_match=e.match_start,e.match_length=En-1,0!==r&&e.prev_length<e.max_lazy_match&&e.strstart-r<=e.w_size-xn&&(e.match_length=Kn(e,r),e.match_length<=5&&(e.strategy===cn||e.match_length===En&&e.strstart-e.match_start>4096)&&(e.match_length=En-1)),e.prev_length>=En&&e.match_length<=e.prev_length){i=e.strstart+e.lookahead-En,n=qr(e,e.strstart-1-e.prev_match,e.prev_length-En),e.lookahead-=e.prev_length-1,e.prev_length-=2;do{++e.strstart<=i&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+En-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart)}while(0!=--e.prev_length);if(e.match_available=0,e.match_length=En-1,e.strstart++,n&&(jn(e,!1),0===e.strm.avail_out))return Dn}else if(e.match_available){if((n=qr(e,0,e.window[e.strstart-1]))&&jn(e,!1),e.strstart++,e.lookahead--,0===e.strm.avail_out)return Dn}else e.match_available=1,e.strstart++,e.lookahead--}return e.match_available&&(n=qr(e,0,e.window[e.strstart-1]),e.match_available=0),e.insert=e.strstart<En-1?e.strstart:En-1,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):e.last_lit&&(jn(e,!1),0===e.strm.avail_out)?Dn:In}function Gn(e,t,r,n,i){this.good_length=e,this.max_lazy=t,this.nice_length=r,this.max_chain=n,this.func=i}function $n(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=gn,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new Yt(2*mn),this.dyn_dtree=new Yt(2*(2*bn+1)),this.bl_tree=new Yt(2*(2*yn+1)),Nn(this.dyn_ltree),Nn(this.dyn_dtree),Nn(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new Yt(kn+1),this.heap=new Yt(2*wn+1),Nn(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new Yt(2*wn+1),Nn(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function Jn(e){var t,r=function(e){var t;return e&&e.state?(e.total_in=e.total_out=0,e.data_type=_n,(t=e.state).pending=0,t.pending_out=0,t.wrap<0&&(t.wrap=-t.wrap),t.status=t.wrap?An:Mn,e.adler=2===t.wrap?0:1,t.last_flush=Qr,Wr(t),on):Hn(e,sn)}(e);return r===on&&((t=e.state).window_size=2*t.w_size,Nn(t.head),t.max_lazy_match=Jr[t.level].max_lazy,t.good_match=Jr[t.level].good_length,t.nice_match=Jr[t.level].nice_length,t.max_chain_length=Jr[t.level].max_chain,t.strstart=0,t.block_start=0,t.lookahead=0,t.insert=0,t.match_length=t.prev_length=En-1,t.match_available=0,t.ins_h=0),r}function Qn(e,t){var r,n,i,o;if(!e||!e.state||t>nn||t<0)return e?Hn(e,sn):sn;if(n=e.state,!e.output||!e.input&&0!==e.avail_in||n.status===Cn&&t!==rn)return Hn(e,0===e.avail_out?ln:sn);if(n.strm=e,r=n.last_flush,n.last_flush=t,n.status===An)if(2===n.wrap)e.adler=0,Wn(n,31),Wn(n,139),Wn(n,8),n.gzhead?(Wn(n,(n.gzhead.text?1:0)+(n.gzhead.hcrc?2:0)+(n.gzhead.extra?4:0)+(n.gzhead.name?8:0)+(n.gzhead.comment?16:0)),Wn(n,255&n.gzhead.time),Wn(n,n.gzhead.time>>8&255),Wn(n,n.gzhead.time>>16&255),Wn(n,n.gzhead.time>>24&255),Wn(n,9===n.level?2:n.strategy>=un||n.level<2?4:0),Wn(n,255&n.gzhead.os),n.gzhead.extra&&n.gzhead.extra.length&&(Wn(n,255&n.gzhead.extra.length),Wn(n,n.gzhead.extra.length>>8&255)),n.gzhead.hcrc&&(e.adler=$r(e.adler,n.pending_buf,n.pending,0)),n.gzindex=0,n.status=Bn):(Wn(n,0),Wn(n,0),Wn(n,0),Wn(n,0),Wn(n,0),Wn(n,9===n.level?2:n.strategy>=un||n.level<2?4:0),Wn(n,Un),n.status=Mn);else{var a=gn+(n.w_bits-8<<4)<<8;a|=(n.strategy>=un||n.level<2?0:n.level<6?1:6===n.level?2:3)<<6,0!==n.strstart&&(a|=Rn),a+=31-a%31,n.status=Mn,Yn(n,a),0!==n.strstart&&(Yn(n,e.adler>>>16),Yn(n,65535&e.adler)),e.adler=1}if(n.status===Bn)if(n.gzhead.extra){for(i=n.pending;n.gzindex<(65535&n.gzhead.extra.length)&&(n.pending!==n.pending_buf_size||(n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),Zn(e),i=n.pending,n.pending!==n.pending_buf_size));)Wn(n,255&n.gzhead.extra[n.gzindex]),n.gzindex++;n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),n.gzindex===n.gzhead.extra.length&&(n.gzindex=0,n.status=zn)}else n.status=zn;if(n.status===zn)if(n.gzhead.name){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),Zn(e),i=n.pending,n.pending===n.pending_buf_size)){o=1;break}o=n.gzindex<n.gzhead.name.length?255&n.gzhead.name.charCodeAt(n.gzindex++):0,Wn(n,o)}while(0!==o);n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),0===o&&(n.gzindex=0,n.status=Ln)}else n.status=Ln;if(n.status===Ln)if(n.gzhead.comment){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),Zn(e),i=n.pending,n.pending===n.pending_buf_size)){o=1;break}o=n.gzindex<n.gzhead.comment.length?255&n.gzhead.comment.charCodeAt(n.gzindex++):0,Wn(n,o)}while(0!==o);n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),0===o&&(n.status=Tn)}else n.status=Tn;if(n.status===Tn&&(n.gzhead.hcrc?(n.pending+2>n.pending_buf_size&&Zn(e),n.pending+2<=n.pending_buf_size&&(Wn(n,255&e.adler),Wn(n,e.adler>>8&255),e.adler=0,n.status=Mn)):n.status=Mn),0!==n.pending){if(Zn(e),0===e.avail_out)return n.last_flush=-1,on}else if(0===e.avail_in&&Fn(t)<=Fn(r)&&t!==rn)return Hn(e,ln);if(n.status===Cn&&0!==e.avail_in)return Hn(e,ln);if(0!==e.avail_in||0!==n.lookahead||t!==Qr&&n.status!==Cn){var s=n.strategy===un?function(e,t){for(var r;;){if(0===e.lookahead&&(Xn(e),0===e.lookahead)){if(t===Qr)return Dn;break}if(e.match_length=0,r=qr(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(jn(e,!1),0===e.strm.avail_out))return Dn}return e.insert=0,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):e.last_lit&&(jn(e,!1),0===e.strm.avail_out)?Dn:In}(n,t):n.strategy===dn?function(e,t){for(var r,n,i,o,a=e.window;;){if(e.lookahead<=Sn){if(Xn(e),e.lookahead<=Sn&&t===Qr)return Dn;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=En&&e.strstart>0&&(n=a[i=e.strstart-1])===a[++i]&&n===a[++i]&&n===a[++i]){o=e.strstart+Sn;do{}while(n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&i<o);e.match_length=Sn-(o-i),e.match_length>e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=En?(r=qr(e,1,e.match_length-En),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=qr(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(jn(e,!1),0===e.strm.avail_out))return Dn}return e.insert=0,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):e.last_lit&&(jn(e,!1),0===e.strm.avail_out)?Dn:In}(n,t):Jr[n.level].func(n,t);if(s!==Pn&&s!==On||(n.status=Cn),s===Dn||s===Pn)return 0===e.avail_out&&(n.last_flush=-1),on;if(s===In&&(t===en?Kr(n):t!==nn&&(Yr(n,0,0,!1),t===tn&&(Nn(n.head),0===n.lookahead&&(n.strstart=0,n.block_start=0,n.insert=0))),Zn(e),0===e.avail_out))return n.last_flush=-1,on}return t!==rn?on:n.wrap<=0?an:(2===n.wrap?(Wn(n,255&e.adler),Wn(n,e.adler>>8&255),Wn(n,e.adler>>16&255),Wn(n,e.adler>>24&255),Wn(n,255&e.total_in),Wn(n,e.total_in>>8&255),Wn(n,e.total_in>>16&255),Wn(n,e.total_in>>24&255)):(Yn(n,e.adler>>>16),Yn(n,65535&e.adler)),Zn(e),n.wrap>0&&(n.wrap=-n.wrap),0!==n.pending?on:an)}Jr=[new Gn(0,0,0,0,function(e,t){var r=65535;for(r>e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(Xn(e),0===e.lookahead&&t===Qr)return Dn;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var n=e.block_start+r;if((0===e.strstart||e.strstart>=n)&&(e.lookahead=e.strstart-n,e.strstart=n,jn(e,!1),0===e.strm.avail_out))return Dn;if(e.strstart-e.block_start>=e.w_size-xn&&(jn(e,!1),0===e.strm.avail_out))return Dn}return e.insert=0,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):(e.strstart>e.block_start&&(jn(e,!1),e.strm.avail_out),Dn)}),new Gn(4,4,8,4,qn),new Gn(4,5,16,8,qn),new Gn(4,6,32,32,qn),new Gn(4,4,16,16,Vn),new Gn(8,16,32,32,Vn),new Gn(8,16,128,128,Vn),new Gn(8,32,128,256,Vn),new Gn(32,128,258,1024,Vn),new Gn(32,258,258,4096,Vn)];var ei=30,ti=12;function ri(e,t){var r,n,i,o,a,s,h,l,f,c,u,d,p,_,g,v,w,b,y,m,k,E,S,x,R;r=e.state,n=e.next_in,x=e.input,i=n+(e.avail_in-5),o=e.next_out,R=e.output,a=o-(t-e.avail_out),s=o+(e.avail_out-257),h=r.dmax,l=r.wsize,f=r.whave,c=r.wnext,u=r.window,d=r.hold,p=r.bits,_=r.lencode,g=r.distcode,v=(1<<r.lenbits)-1,w=(1<<r.distbits)-1;e:do{p<15&&(d+=x[n++]<<p,p+=8,d+=x[n++]<<p,p+=8),b=_[d&v];t:for(;;){if(d>>>=y=b>>>24,p-=y,0===(y=b>>>16&255))R[o++]=65535&b;else{if(!(16&y)){if(0==(64&y)){b=_[(65535&b)+(d&(1<<y)-1)];continue t}if(32&y){r.mode=ti;break e}e.msg="invalid literal/length code",r.mode=ei;break e}m=65535&b,(y&=15)&&(p<y&&(d+=x[n++]<<p,p+=8),m+=d&(1<<y)-1,d>>>=y,p-=y),p<15&&(d+=x[n++]<<p,p+=8,d+=x[n++]<<p,p+=8),b=g[d&w];r:for(;;){if(d>>>=y=b>>>24,p-=y,!(16&(y=b>>>16&255))){if(0==(64&y)){b=g[(65535&b)+(d&(1<<y)-1)];continue r}e.msg="invalid distance code",r.mode=ei;break e}if(k=65535&b,p<(y&=15)&&(d+=x[n++]<<p,(p+=8)<y&&(d+=x[n++]<<p,p+=8)),(k+=d&(1<<y)-1)>h){e.msg="invalid distance too far back",r.mode=ei;break e}if(d>>>=y,p-=y,k>(y=o-a)){if((y=k-y)>f&&r.sane){e.msg="invalid distance too far back",r.mode=ei;break e}if(E=0,S=u,0===c){if(E+=l-y,y<m){m-=y;do{R[o++]=u[E++]}while(--y);E=o-k,S=R}}else if(c<y){if(E+=l+c-y,(y-=c)<m){m-=y;do{R[o++]=u[E++]}while(--y);if(E=0,c<m){m-=y=c;do{R[o++]=u[E++]}while(--y);E=o-k,S=R}}}else if(E+=c-y,y<m){m-=y;do{R[o++]=u[E++]}while(--y);E=o-k,S=R}for(;m>2;)R[o++]=S[E++],R[o++]=S[E++],R[o++]=S[E++],m-=3;m&&(R[o++]=S[E++],m>1&&(R[o++]=S[E++]))}else{E=o-k;do{R[o++]=R[E++],R[o++]=R[E++],R[o++]=R[E++],m-=3}while(m>2);m&&(R[o++]=R[E++],m>1&&(R[o++]=R[E++]))}break}}break}}while(n<i&&o<s);n-=m=p>>3,d&=(1<<(p-=m<<3))-1,e.next_in=n,e.next_out=o,e.avail_in=n<i?i-n+5:5-(n-i),e.avail_out=o<s?s-o+257:257-(o-s),r.hold=d,r.bits=p}var ni=15,ii=852,oi=592,ai=0,si=1,hi=2,li=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],fi=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],ci=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],ui=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];function di(e,t,r,n,i,o,a,s){var h,l,f,c,u,d,p,_,g,v=s.bits,w=0,b=0,y=0,m=0,k=0,E=0,S=0,x=0,R=0,A=0,B=null,z=0,L=new Yt(ni+1),T=new Yt(ni+1),M=null,C=0;for(w=0;w<=ni;w++)L[w]=0;for(b=0;b<n;b++)L[t[r+b]]++;for(k=v,m=ni;m>=1&&0===L[m];m--);if(k>m&&(k=m),0===m)return i[o++]=20971520,i[o++]=20971520,s.bits=1,0;for(y=1;y<m&&0===L[y];y++);for(k<y&&(k=y),x=1,w=1;w<=ni;w++)if(x<<=1,(x-=L[w])<0)return-1;if(x>0&&(e===ai||1!==m))return-1;for(T[1]=0,w=1;w<ni;w++)T[w+1]=T[w]+L[w];for(b=0;b<n;b++)0!==t[r+b]&&(a[T[t[r+b]]++]=b);if(e===ai?(B=M=a,d=19):e===si?(B=li,z-=257,M=fi,C-=257,d=256):(B=ci,M=ui,d=-1),A=0,b=0,w=y,u=o,E=k,S=0,f=-1,c=(R=1<<k)-1,e===si&&R>ii||e===hi&&R>oi)return 1;for(;;){p=w-S,a[b]<d?(_=0,g=a[b]):a[b]>d?(_=M[C+a[b]],g=B[z+a[b]]):(_=96,g=0),h=1<<w-S,y=l=1<<E;do{i[u+(A>>S)+(l-=h)]=p<<24|_<<16|g|0}while(0!==l);for(h=1<<w-1;A&h;)h>>=1;if(0!==h?(A&=h-1,A+=h):A=0,b++,0==--L[w]){if(w===m)break;w=t[r+a[b]]}if(w>k&&(A&c)!==f){for(0===S&&(S=k),u+=y,x=1<<(E=w-S);E+S<m&&!((x-=L[E+S])<=0);)E++,x<<=1;if(R+=1<<E,e===si&&R>ii||e===hi&&R>oi)return 1;i[f=A&c]=k<<24|E<<16|u-o|0}}return 0!==A&&(i[u+A]=w-S<<24|64<<16|0),s.bits=k,0}var pi=0,_i=1,gi=2,vi=4,wi=5,bi=6,yi=0,mi=1,ki=2,Ei=-2,Si=-3,xi=-4,Ri=-5,Ai=8,Bi=1,zi=2,Li=3,Ti=4,Mi=5,Ci=6,Di=7,Ii=8,Pi=9,Oi=10,Ui=11,Hi=12,Fi=13,Ni=14,Zi=15,ji=16,Wi=17,Yi=18,Ki=19,Xi=20,qi=21,Vi=22,Gi=23,$i=24,Ji=25,Qi=26,eo=27,to=28,ro=29,no=30,io=31,oo=32,ao=852,so=592;function ho(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function lo(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new Yt(320),this.work=new Yt(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function fo(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,function(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=Bi,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new Kt(ao),t.distcode=t.distdyn=new Kt(so),t.sane=1,t.back=-1,yi):Ei}(e)):Ei}function co(e,t){var r,n;return e?(n=new lo,e.state=n,n.window=null,(r=function(e,t){var r,n;return e&&e.state?(n=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||t>15)?Ei:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=r,n.wbits=t,fo(e))):Ei}(e,t))!==yi&&(e.state=null),r):Ei}var uo,po,_o=!0;function go(e){if(_o){var t;for(uo=new Kt(512),po=new Kt(32),t=0;t<144;)e.lens[t++]=8;for(;t<256;)e.lens[t++]=9;for(;t<280;)e.lens[t++]=7;for(;t<288;)e.lens[t++]=8;for(di(_i,e.lens,0,288,uo,0,e.work,{bits:9}),t=0;t<32;)e.lens[t++]=5;di(gi,e.lens,0,32,po,0,e.work,{bits:5}),_o=!1}e.lencode=uo,e.lenbits=9,e.distcode=po,e.distbits=5}function vo(e,t){var r,n,i,o,a,s,h,l,f,c,u,d,p,_,g,v,w,b,y,m,k,E,S,x,R=0,A=new Wt(4),B=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!e||!e.state||!e.output||!e.input&&0!==e.avail_in)return Ei;(r=e.state).mode===Hi&&(r.mode=Fi),a=e.next_out,i=e.output,h=e.avail_out,o=e.next_in,n=e.input,s=e.avail_in,l=r.hold,f=r.bits,c=s,u=h,E=yi;e:for(;;)switch(r.mode){case Bi:if(0===r.wrap){r.mode=Fi;break}for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(2&r.wrap&&35615===l){r.check=0,A[0]=255&l,A[1]=l>>>8&255,r.check=$r(r.check,A,2,0),l=0,f=0,r.mode=zi;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&l)<<8)+(l>>8))%31){e.msg="incorrect header check",r.mode=no;break}if((15&l)!==Ai){e.msg="unknown compression method",r.mode=no;break}if(f-=4,k=8+(15&(l>>>=4)),0===r.wbits)r.wbits=k;else if(k>r.wbits){e.msg="invalid window size",r.mode=no;break}r.dmax=1<<k,e.adler=r.check=1,r.mode=512&l?Oi:Hi,l=0,f=0;break;case zi:for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(r.flags=l,(255&r.flags)!==Ai){e.msg="unknown compression method",r.mode=no;break}if(57344&r.flags){e.msg="unknown header flags set",r.mode=no;break}r.head&&(r.head.text=l>>8&1),512&r.flags&&(A[0]=255&l,A[1]=l>>>8&255,r.check=$r(r.check,A,2,0)),l=0,f=0,r.mode=Li;case Li:for(;f<32;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.head&&(r.head.time=l),512&r.flags&&(A[0]=255&l,A[1]=l>>>8&255,A[2]=l>>>16&255,A[3]=l>>>24&255,r.check=$r(r.check,A,4,0)),l=0,f=0,r.mode=Ti;case Ti:for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.head&&(r.head.xflags=255&l,r.head.os=l>>8),512&r.flags&&(A[0]=255&l,A[1]=l>>>8&255,r.check=$r(r.check,A,2,0)),l=0,f=0,r.mode=Mi;case Mi:if(1024&r.flags){for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.length=l,r.head&&(r.head.extra_len=l),512&r.flags&&(A[0]=255&l,A[1]=l>>>8&255,r.check=$r(r.check,A,2,0)),l=0,f=0}else r.head&&(r.head.extra=null);r.mode=Ci;case Ci:if(1024&r.flags&&((d=r.length)>s&&(d=s),d&&(r.head&&(k=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),jt(r.head.extra,n,o,d,k)),512&r.flags&&(r.check=$r(r.check,n,d,o)),s-=d,o+=d,r.length-=d),r.length))break e;r.length=0,r.mode=Di;case Di:if(2048&r.flags){if(0===s)break e;d=0;do{k=n[o+d++],r.head&&k&&r.length<65536&&(r.head.name+=String.fromCharCode(k))}while(k&&d<s);if(512&r.flags&&(r.check=$r(r.check,n,d,o)),s-=d,o+=d,k)break e}else r.head&&(r.head.name=null);r.length=0,r.mode=Ii;case Ii:if(4096&r.flags){if(0===s)break e;d=0;do{k=n[o+d++],r.head&&k&&r.length<65536&&(r.head.comment+=String.fromCharCode(k))}while(k&&d<s);if(512&r.flags&&(r.check=$r(r.check,n,d,o)),s-=d,o+=d,k)break e}else r.head&&(r.head.comment=null);r.mode=Pi;case Pi:if(512&r.flags){for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(l!==(65535&r.check)){e.msg="header crc mismatch",r.mode=no;break}l=0,f=0}r.head&&(r.head.hcrc=r.flags>>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=Hi;break;case Oi:for(;f<32;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}e.adler=r.check=ho(l),l=0,f=0,r.mode=Ui;case Ui:if(0===r.havedict)return e.next_out=a,e.avail_out=h,e.next_in=o,e.avail_in=s,r.hold=l,r.bits=f,ki;e.adler=r.check=1,r.mode=Hi;case Hi:if(t===wi||t===bi)break e;case Fi:if(r.last){l>>>=7&f,f-=7&f,r.mode=eo;break}for(;f<3;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}switch(r.last=1&l,f-=1,3&(l>>>=1)){case 0:r.mode=Ni;break;case 1:if(go(r),r.mode=Xi,t===bi){l>>>=2,f-=2;break e}break;case 2:r.mode=Wi;break;case 3:e.msg="invalid block type",r.mode=no}l>>>=2,f-=2;break;case Ni:for(l>>>=7&f,f-=7&f;f<32;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if((65535&l)!=(l>>>16^65535)){e.msg="invalid stored block lengths",r.mode=no;break}if(r.length=65535&l,l=0,f=0,r.mode=Zi,t===bi)break e;case Zi:r.mode=ji;case ji:if(d=r.length){if(d>s&&(d=s),d>h&&(d=h),0===d)break e;jt(i,n,o,d,a),s-=d,o+=d,h-=d,a+=d,r.length-=d;break}r.mode=Hi;break;case Wi:for(;f<14;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(r.nlen=257+(31&l),l>>>=5,f-=5,r.ndist=1+(31&l),l>>>=5,f-=5,r.ncode=4+(15&l),l>>>=4,f-=4,r.nlen>286||r.ndist>30){e.msg="too many length or distance symbols",r.mode=no;break}r.have=0,r.mode=Yi;case Yi:for(;r.have<r.ncode;){for(;f<3;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.lens[B[r.have++]]=7&l,l>>>=3,f-=3}for(;r.have<19;)r.lens[B[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,S={bits:r.lenbits},E=di(pi,r.lens,0,19,r.lencode,0,r.work,S),r.lenbits=S.bits,E){e.msg="invalid code lengths set",r.mode=no;break}r.have=0,r.mode=Ki;case Ki:for(;r.have<r.nlen+r.ndist;){for(;v=(R=r.lencode[l&(1<<r.lenbits)-1])>>>16&255,w=65535&R,!((g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(w<16)l>>>=g,f-=g,r.lens[r.have++]=w;else{if(16===w){for(x=g+2;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(l>>>=g,f-=g,0===r.have){e.msg="invalid bit length repeat",r.mode=no;break}k=r.lens[r.have-1],d=3+(3&l),l>>>=2,f-=2}else if(17===w){for(x=g+3;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}f-=g,k=0,d=3+(7&(l>>>=g)),l>>>=3,f-=3}else{for(x=g+7;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}f-=g,k=0,d=11+(127&(l>>>=g)),l>>>=7,f-=7}if(r.have+d>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=no;break}for(;d--;)r.lens[r.have++]=k}}if(r.mode===no)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=no;break}if(r.lenbits=9,S={bits:r.lenbits},E=di(_i,r.lens,0,r.nlen,r.lencode,0,r.work,S),r.lenbits=S.bits,E){e.msg="invalid literal/lengths set",r.mode=no;break}if(r.distbits=6,r.distcode=r.distdyn,S={bits:r.distbits},E=di(gi,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,S),r.distbits=S.bits,E){e.msg="invalid distances set",r.mode=no;break}if(r.mode=Xi,t===bi)break e;case Xi:r.mode=qi;case qi:if(s>=6&&h>=258){e.next_out=a,e.avail_out=h,e.next_in=o,e.avail_in=s,r.hold=l,r.bits=f,ri(e,u),a=e.next_out,i=e.output,h=e.avail_out,o=e.next_in,n=e.input,s=e.avail_in,l=r.hold,f=r.bits,r.mode===Hi&&(r.back=-1);break}for(r.back=0;v=(R=r.lencode[l&(1<<r.lenbits)-1])>>>16&255,w=65535&R,!((g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(v&&0==(240&v)){for(b=g,y=v,m=w;v=(R=r.lencode[m+((l&(1<<b+y)-1)>>b)])>>>16&255,w=65535&R,!(b+(g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}l>>>=b,f-=b,r.back+=b}if(l>>>=g,f-=g,r.back+=g,r.length=w,0===v){r.mode=Qi;break}if(32&v){r.back=-1,r.mode=Hi;break}if(64&v){e.msg="invalid literal/length code",r.mode=no;break}r.extra=15&v,r.mode=Vi;case Vi:if(r.extra){for(x=r.extra;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.length+=l&(1<<r.extra)-1,l>>>=r.extra,f-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=Gi;case Gi:for(;v=(R=r.distcode[l&(1<<r.distbits)-1])>>>16&255,w=65535&R,!((g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(0==(240&v)){for(b=g,y=v,m=w;v=(R=r.distcode[m+((l&(1<<b+y)-1)>>b)])>>>16&255,w=65535&R,!(b+(g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}l>>>=b,f-=b,r.back+=b}if(l>>>=g,f-=g,r.back+=g,64&v){e.msg="invalid distance code",r.mode=no;break}r.offset=w,r.extra=15&v,r.mode=$i;case $i:if(r.extra){for(x=r.extra;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.offset+=l&(1<<r.extra)-1,l>>>=r.extra,f-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=no;break}r.mode=Ji;case Ji:if(0===h)break e;if(d=u-h,r.offset>d){if((d=r.offset-d)>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=no;break}d>r.wnext?(d-=r.wnext,p=r.wsize-d):p=r.wnext-d,d>r.length&&(d=r.length),_=r.window}else _=i,p=a-r.offset,d=r.length;d>h&&(d=h),h-=d,r.length-=d;do{i[a++]=_[p++]}while(--d);0===r.length&&(r.mode=qi);break;case Qi:if(0===h)break e;i[a++]=r.length,h--,r.mode=qi;break;case eo:if(r.wrap){for(;f<32;){if(0===s)break e;s--,l|=n[o++]<<f,f+=8}if(u-=h,e.total_out+=u,r.total+=u,u&&(e.adler=r.check=r.flags?$r(r.check,i,u,a-u):Vr(r.check,i,u,a-u)),u=h,(r.flags?l:ho(l))!==r.check){e.msg="incorrect data check",r.mode=no;break}l=0,f=0}r.mode=to;case to:if(r.wrap&&r.flags){for(;f<32;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(l!==(4294967295&r.total)){e.msg="incorrect length check",r.mode=no;break}l=0,f=0}r.mode=ro;case ro:E=mi;break e;case no:E=Si;break e;case io:return xi;case oo:default:return Ei}return e.next_out=a,e.avail_out=h,e.next_in=o,e.avail_in=s,r.hold=l,r.bits=f,(r.wsize||u!==e.avail_out&&r.mode<no&&(r.mode<eo||t!==vi))&&function(e,t,r,n){var i,o=e.state;null===o.window&&(o.wsize=1<<o.wbits,o.wnext=0,o.whave=0,o.window=new Wt(o.wsize)),n>=o.wsize?(jt(o.window,t,r-o.wsize,o.wsize,0),o.wnext=0,o.whave=o.wsize):((i=o.wsize-o.wnext)>n&&(i=n),jt(o.window,t,r-n,i,o.wnext),(n-=i)?(jt(o.window,t,r-n,n,0),o.wnext=n,o.whave=o.wsize):(o.wnext+=i,o.wnext===o.wsize&&(o.wnext=0),o.whave<o.wsize&&(o.whave+=i)))}(e,e.output,e.next_out,u-e.avail_out),c-=e.avail_in,u-=e.avail_out,e.total_in+=c,e.total_out+=u,r.total+=u,r.wrap&&u&&(e.adler=r.check=r.flags?$r(r.check,i,u,e.next_out-u):Vr(r.check,i,u,e.next_out-u)),e.data_type=r.bits+(r.last?64:0)+(r.mode===Hi?128:0)+(r.mode===Xi||r.mode===Zi?256:0),(0===c&&0===u||t===vi)&&E===yi&&(E=Ri),E}var wo,bo=1,yo=7;function mo(e){if(e<bo||e>yo)throw new TypeError("Bad argument");this.mode=e,this.init_done=!1,this.write_in_progress=!1,this.pending_close=!1,this.windowBits=0,this.level=0,this.memLevel=0,this.strategy=0,this.dictionary=null}function ko(e,t){for(var r=0;r<e.length;r++)this[t+r]=e[r]}mo.prototype.init=function(e,t,r,n,i){var o;switch(this.windowBits=e,this.level=t,this.memLevel=r,this.strategy=n,3!==this.mode&&4!==this.mode||(this.windowBits+=16),this.mode===yo&&(this.windowBits+=32),5!==this.mode&&6!==this.mode||(this.windowBits=-this.windowBits),this.strm=new Zt,this.mode){case bo:case 3:case 5:o=function(e,t,r,n,i,o){if(!e)return sn;var a=1;if(t===fn&&(t=6),n<0?(a=0,n=-n):n>15&&(a=2,n-=16),i<1||i>vn||r!==gn||n<8||n>15||t<0||t>9||o<0||o>pn)return Hn(e,sn);8===n&&(n=9);var s=new $n;return e.state=s,s.strm=e,s.wrap=a,s.gzhead=null,s.w_bits=n,s.w_size=1<<s.w_bits,s.w_mask=s.w_size-1,s.hash_bits=i+7,s.hash_size=1<<s.hash_bits,s.hash_mask=s.hash_size-1,s.hash_shift=~~((s.hash_bits+En-1)/En),s.window=new Wt(2*s.w_size),s.head=new Yt(s.hash_size),s.prev=new Yt(s.w_size),s.lit_bufsize=1<<i+6,s.pending_buf_size=4*s.lit_bufsize,s.pending_buf=new Wt(s.pending_buf_size),s.d_buf=1*s.lit_bufsize,s.l_buf=3*s.lit_bufsize,s.level=t,s.strategy=o,s.method=r,Jn(e)}(this.strm,this.level,8,this.windowBits,this.memLevel,this.strategy);break;case 2:case 4:case 6:case yo:o=co(this.strm,this.windowBits);break;default:throw new Error("Unknown mode "+this.mode)}0===o?(this.write_in_progress=!1,this.init_done=!0):this._error(o)},mo.prototype.params=function(){throw new Error("deflateParams Not supported")},mo.prototype._writeCheck=function(){if(!this.init_done)throw new Error("write before init");if(0===this.mode)throw new Error("already finalized");if(this.write_in_progress)throw new Error("write already in progress");if(this.pending_close)throw new Error("close is pending")},mo.prototype.write=function(e,t,r,n,i,o,a){this._writeCheck(),this.write_in_progress=!0;var s=this;return de(function(){s.write_in_progress=!1;var h=s._write(e,t,r,n,i,o,a);s.callback(h[0],h[1]),s.pending_close&&s.close()}),this},mo.prototype.writeSync=function(e,t,r,n,i,o,a){return this._writeCheck(),this._write(e,t,r,n,i,o,a)},mo.prototype._write=function(e,t,r,n,i,o,a){if(this.write_in_progress=!0,0!==e&&1!==e&&2!==e&&3!==e&&4!==e&&5!==e)throw new Error("Invalid flush value");null==t&&(t=new p(0),n=0,r=0),i._set?i.set=i._set:i.set=ko;var s,h=this.strm;switch(h.avail_in=n,h.input=t,h.next_in=r,h.avail_out=a,h.output=i,h.next_out=o,this.mode){case bo:case 3:case 5:s=Qn(h,e);break;case yo:case 2:case 4:case 6:s=vo(h,e);break;default:throw new Error("Unknown mode "+this.mode)}return 1!==s&&0!==s&&this._error(s),this.write_in_progress=!1,[h.avail_in,h.avail_out]},mo.prototype.close=function(){this.write_in_progress?this.pending_close=!0:(this.pending_close=!1,this.mode===bo||3===this.mode||5===this.mode?function(e){var t;e&&e.state&&((t=e.state.status)!==An&&t!==Bn&&t!==zn&&t!==Ln&&t!==Tn&&t!==Mn&&t!==Cn?Hn(e,sn):(e.state=null,t===Mn&&Hn(e,hn)))}(this.strm):function(e){if(!e||!e.state)return Ei;var t=e.state;t.window&&(t.window=null),e.state=null}(this.strm),this.mode=0)},mo.prototype.reset=function(){switch(this.mode){case bo:case 5:wo=Jn(this.strm);break;case 2:case 6:wo=fo(this.strm)}0!==wo&&this._error(wo)},mo.prototype._error=function(e){this.onerror(Nt[e]+": "+this.strm.msg,e),this.write_in_progress=!1,this.pending_close&&this.close()};var Eo=Object.freeze({NONE:0,DEFLATE:bo,INFLATE:2,GZIP:3,GUNZIP:4,DEFLATERAW:5,INFLATERAW:6,UNZIP:yo,Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8,Zlib:mo});var So={};Object.keys(Eo).forEach(function(e){So[e]=Eo[e]}),So.Z_MIN_WINDOWBITS=8,So.Z_MAX_WINDOWBITS=15,So.Z_DEFAULT_WINDOWBITS=15,So.Z_MIN_CHUNK=64,So.Z_MAX_CHUNK=1/0,So.Z_DEFAULT_CHUNK=16384,So.Z_MIN_MEMLEVEL=1,So.Z_MAX_MEMLEVEL=9,So.Z_DEFAULT_MEMLEVEL=8,So.Z_MIN_LEVEL=-1,So.Z_MAX_LEVEL=9,So.Z_DEFAULT_LEVEL=So.Z_DEFAULT_COMPRESSION;var xo={Z_OK:So.Z_OK,Z_STREAM_END:So.Z_STREAM_END,Z_NEED_DICT:So.Z_NEED_DICT,Z_ERRNO:So.Z_ERRNO,Z_STREAM_ERROR:So.Z_STREAM_ERROR,Z_DATA_ERROR:So.Z_DATA_ERROR,Z_MEM_ERROR:So.Z_MEM_ERROR,Z_BUF_ERROR:So.Z_BUF_ERROR,Z_VERSION_ERROR:So.Z_VERSION_ERROR};function Ro(e,t,r){var n=[],i=0;function o(){for(var t;null!==(t=e.read());)n.push(t),i+=t.length;e.once("readable",o)}function a(){var t=p.concat(n,i);n=[],r(null,t),e.close()}e.on("error",function(t){e.removeListener("end",a),e.removeListener("readable",o),r(t)}),e.on("end",a),e.end(t),o()}function Ao(e,t){if("string"==typeof t&&(t=new p(t)),!$(t))throw new TypeError("Not a string or buffer");var r=So.Z_FINISH;return e._processChunk(t,r)}function Bo(e){if(!(this instanceof Bo))return new Bo(e);Io.call(this,e,So.DEFLATE)}function zo(e){if(!(this instanceof zo))return new zo(e);Io.call(this,e,So.INFLATE)}function Lo(e){if(!(this instanceof Lo))return new Lo(e);Io.call(this,e,So.GZIP)}function To(e){if(!(this instanceof To))return new To(e);Io.call(this,e,So.GUNZIP)}function Mo(e){if(!(this instanceof Mo))return new Mo(e);Io.call(this,e,So.DEFLATERAW)}function Co(e){if(!(this instanceof Co))return new Co(e);Io.call(this,e,So.INFLATERAW)}function Do(e){if(!(this instanceof Do))return new Do(e);Io.call(this,e,So.UNZIP)}function Io(e,t){if(this._opts=e=e||{},this._chunkSize=e.chunkSize||So.Z_DEFAULT_CHUNK,Ot.call(this,e),e.flush&&e.flush!==So.Z_NO_FLUSH&&e.flush!==So.Z_PARTIAL_FLUSH&&e.flush!==So.Z_SYNC_FLUSH&&e.flush!==So.Z_FULL_FLUSH&&e.flush!==So.Z_FINISH&&e.flush!==So.Z_BLOCK)throw new Error("Invalid flush flag: "+e.flush);if(this._flushFlag=e.flush||So.Z_NO_FLUSH,e.chunkSize&&(e.chunkSize<So.Z_MIN_CHUNK||e.chunkSize>So.Z_MAX_CHUNK))throw new Error("Invalid chunk size: "+e.chunkSize);if(e.windowBits&&(e.windowBits<So.Z_MIN_WINDOWBITS||e.windowBits>So.Z_MAX_WINDOWBITS))throw new Error("Invalid windowBits: "+e.windowBits);if(e.level&&(e.level<So.Z_MIN_LEVEL||e.level>So.Z_MAX_LEVEL))throw new Error("Invalid compression level: "+e.level);if(e.memLevel&&(e.memLevel<So.Z_MIN_MEMLEVEL||e.memLevel>So.Z_MAX_MEMLEVEL))throw new Error("Invalid memLevel: "+e.memLevel);if(e.strategy&&e.strategy!=So.Z_FILTERED&&e.strategy!=So.Z_HUFFMAN_ONLY&&e.strategy!=So.Z_RLE&&e.strategy!=So.Z_FIXED&&e.strategy!=So.Z_DEFAULT_STRATEGY)throw new Error("Invalid strategy: "+e.strategy);if(e.dictionary&&!$(e.dictionary))throw new Error("Invalid dictionary: it should be a Buffer instance");this._binding=new So.Zlib(t);var r=this;this._hadError=!1,this._binding.onerror=function(e,t){r._binding=null,r._hadError=!0;var n=new Error(e);n.errno=t,n.code=So.codes[t],r.emit("error",n)};var n=So.Z_DEFAULT_COMPRESSION;"number"==typeof e.level&&(n=e.level);var i=So.Z_DEFAULT_STRATEGY;"number"==typeof e.strategy&&(i=e.strategy),this._binding.init(e.windowBits||So.Z_DEFAULT_WINDOWBITS,n,e.memLevel||So.Z_DEFAULT_MEMLEVEL,i,e.dictionary),this._buffer=new p(this._chunkSize),this._offset=0,this._closed=!1,this._level=n,this._strategy=i,this.once("end",this.close)}Object.keys(xo).forEach(function(e){xo[xo[e]]=e}),Be(Io,Ot),Io.prototype.params=function(e,t,r){if(e<So.Z_MIN_LEVEL||e>So.Z_MAX_LEVEL)throw new RangeError("Invalid compression level: "+e);if(t!=So.Z_FILTERED&&t!=So.Z_HUFFMAN_ONLY&&t!=So.Z_RLE&&t!=So.Z_FIXED&&t!=So.Z_DEFAULT_STRATEGY)throw new TypeError("Invalid strategy: "+t);if(this._level!==e||this._strategy!==t){var n=this;this.flush(So.Z_SYNC_FLUSH,function(){n._binding.params(e,t),n._hadError||(n._level=e,n._strategy=t,r&&r())})}else de(r)},Io.prototype.reset=function(){return this._binding.reset()},Io.prototype._flush=function(e){this._transform(new p(0),"",e)},Io.prototype.flush=function(e,t){var r=this._writableState;if(("function"==typeof e||void 0===e&&!t)&&(t=e,e=So.Z_FULL_FLUSH),r.ended)t&&de(t);else if(r.ending)t&&this.once("end",t);else if(r.needDrain){var n=this;this.once("drain",function(){n.flush(t)})}else this._flushFlag=e,this.write(new p(0),"",t)},Io.prototype.close=function(e){if(e&&de(e),!this._closed){this._closed=!0,this._binding.close();var t=this;de(function(){t.emit("close")})}},Io.prototype._transform=function(e,t,r){var n,i=this._writableState,o=(i.ending||i.ended)&&(!e||i.length===e.length);if(null===!e&&!$(e))return r(new Error("invalid input"));o?n=So.Z_FINISH:(n=this._flushFlag,e.length>=i.length&&(this._flushFlag=this._opts.flush||So.Z_NO_FLUSH)),this._processChunk(e,n,r)},Io.prototype._processChunk=function(e,t,r){var n=e&&e.length,i=this._chunkSize-this._offset,o=0,a=this,s="function"==typeof r;if(!s){var h,l=[],f=0;this.on("error",function(e){h=e});do{var c=this._binding.writeSync(t,e,o,n,this._buffer,this._offset,i)}while(!this._hadError&&_(c[0],c[1]));if(this._hadError)throw h;var u=p.concat(l,f);return this.close(),u}var d=this._binding.write(t,e,o,n,this._buffer,this._offset,i);function _(h,c){if(!a._hadError){var u=i-c;if(function(e,t){if(!e)throw new Error(t)}(u>=0,"have should not go down"),u>0){var d=a._buffer.slice(a._offset,a._offset+u);a._offset+=u,s?a.push(d):(l.push(d),f+=d.length)}if((0===c||a._offset>=a._chunkSize)&&(i=a._chunkSize,a._offset=0,a._buffer=new p(a._chunkSize)),0===c){if(o+=n-h,n=h,!s)return!0;var g=a._binding.write(t,e,o,n,a._buffer,a._offset,a._chunkSize);return g.callback=_,void(g.buffer=e)}if(!s)return!1;r()}}d.buffer=e,d.callback=_},Be(Bo,Io),Be(zo,Io),Be(Lo,Io),Be(To,Io),Be(Mo,Io),Be(Co,Io),Be(Do,Io);var Po={codes:xo,createDeflate:function(e){return new Bo(e)},createInflate:function(e){return new zo(e)},createDeflateRaw:function(e){return new Mo(e)},createInflateRaw:function(e){return new Co(e)},createGzip:function(e){return new Lo(e)},createGunzip:function(e){return new To(e)},createUnzip:function(e){return new Do(e)},deflate:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Bo(t),e,r)},deflateSync:function(e,t){return Ao(new Bo(t),e)},gzip:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Lo(t),e,r)},gzipSync:function(e,t){return Ao(new Lo(t),e)},deflateRaw:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Mo(t),e,r)},deflateRawSync:function(e,t){return Ao(new Mo(t),e)},unzip:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Do(t),e,r)},unzipSync:function(e,t){return Ao(new Do(t),e)},inflate:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new zo(t),e,r)},inflateSync:function(e,t){return Ao(new zo(t),e)},gunzip:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new To(t),e,r)},gunzipSync:function(e,t){return Ao(new To(t),e)},inflateRaw:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Co(t),e,r)},inflateRawSync:function(e,t){return Ao(new Co(t),e)},Deflate:Bo,Inflate:zo,Gzip:Lo,Gunzip:To,DeflateRaw:Mo,InflateRaw:Co,Unzip:Do,Zlib:Io};export default class{constructor(e,t,r){this.SDKAPPID=e,this.EXPIRETIME=r,this.PRIVATEKEY=t}genTestUserSig(e){return this._isNumber(this.SDKAPPID)?this._isString(this.PRIVATEKEY)?this._isString(e)?this._isNumber(this.EXPIRETIME)?(console.log("sdkAppID="+this.SDKAPPID+" key="+this.PRIVATEKEY+" userID="+e+" expire="+this.EXPIRETIME),this.genSigWithUserbuf(e,this.EXPIRETIME,null)):(console.error("expireTime must be a number"),""):(console.error("userID must be a string"),""):(console.error("privateKey must be a string"),""):(console.error("sdkAppID must be a number"),"")}newBuffer(e,t){return p.from?p.from(e,t):new p(e,t)}unescape(e){return e.replace(/_/g,"=").replace(/\-/g,"/").replace(/\*/g,"+")}escape(e){return e.replace(/\+/g,"*").replace(/\//g,"-").replace(/=/g,"_")}encode(e){return this.escape(this.newBuffer(e).toString("base64"))}decode(e){return this.newBuffer(this.unescape(e),"base64")}base64encode(e){return this.newBuffer(e).toString("base64")}base64decode(e){return this.newBuffer(e,"base64").toString()}_hmacsha256(e,t,r,n){let i="TLS.identifier:"+e+"\n";i+="TLS.sdkappid:"+this.SDKAPPID+"\n",i+="TLS.time:"+t+"\n",i+="TLS.expire:"+r+"\n",null!=n&&(i+="TLS.userbuf:"+n+"\n");let o=te.HmacSHA256(i,this.PRIVATEKEY);return te.enc.Base64.stringify(o)}_utc(){return Math.round(Date.now()/1e3)}_isNumber(e){return null!==e&&("number"==typeof e&&!isNaN(e-0)||"object"==typeof e&&e.constructor===Number)}_isString(e){return"string"==typeof e}genSigWithUserbuf(e,t,r){let n=this._utc(),i={"TLS.ver":"2.0","TLS.identifier":e,"TLS.sdkappid":this.SDKAPPID,"TLS.time":n,"TLS.expire":t},o="";if(null!=r){let a=this.base64encode(r);i["TLS.userbuf"]=a,o=this._hmacsha256(e,n,t,a)}else o=this._hmacsha256(e,n,t,null);i["TLS.sig"]=o;let a=JSON.stringify(i),s=Po.deflateSync(this.newBuffer(a)).toString("base64"),h=this.escape(s);return console.log("ret="+h),h}validate(e){let t=this.decode(e),r=Po.inflateSync(t);console.log("validate ret="+r)}} |
| New file |
| | |
| | | export default { |
| | | extends: [ |
| | | 'stylelint-config-standard', |
| | | 'stylelint-config-standard-vue', |
| | | 'stylelint-config-recess-order', |
| | | ], |
| | | ignoreFiles: [ |
| | | 'dist/**', |
| | | 'src/uni_modules/**', |
| | | 'node_modules/**', |
| | | 'src/static/styles/theme.scss', // 忽略主题文件,因为包含 CSS 自定义属性 |
| | | ], |
| | | rules: { |
| | | // 禁止空代码 |
| | | 'no-empty-source': null, |
| | | // 禁止在覆盖高特异性选择器之后出现低特异性选择器 |
| | | 'no-descending-specificity': null, |
| | | // 不允许未知单位 |
| | | 'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }], |
| | | // 禁止空注释 |
| | | 'comment-no-empty': true, |
| | | // @import 规则必须始终使用字符串表示法。 |
| | | 'import-notation': 'string', |
| | | // 未知的 @ 规则 |
| | | 'at-rule-no-unknown': [ |
| | | true, |
| | | { |
| | | ignoreAtRules: [ |
| | | 'plugin', |
| | | 'apply', |
| | | 'screen', |
| | | 'function', |
| | | 'if', |
| | | 'each', |
| | | 'include', |
| | | 'mixin', |
| | | 'extend', |
| | | 'content', |
| | | 'use', |
| | | ], |
| | | }, |
| | | ], |
| | | 'selector-pseudo-element-no-unknown': [ |
| | | true, |
| | | { |
| | | ignorePseudoElements: ['v-deep'], |
| | | }, |
| | | ], |
| | | 'selector-pseudo-class-no-unknown': [ |
| | | true, |
| | | { |
| | | ignorePseudoClasses: ['deep'], |
| | | }, |
| | | ], |
| | | 'selector-type-no-unknown': [true, { ignoreTypes: ['page', 'radio', 'checkbox', 'scroll-view'] }], |
| | | 'at-rule-no-deprecated': null, |
| | | }, |
| | | }; |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:38:38 |
| | | * @FilePath : \uno.config.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import { |
| | | defineConfig, |
| | | presetIcons, |
| | | transformerDirectives, |
| | | transformerVariantGroup |
| | | } from "unocss" |
| | | import { presetWeapp } from "unocss-preset-weapp" |
| | | import { |
| | | extractorAttributify, |
| | | transformerClass |
| | | } from "unocss-preset-weapp/transformer" |
| | | |
| | | const { |
| | | presetWeappAttributify, |
| | | transformerAttributify |
| | | } = extractorAttributify() |
| | | |
| | | export default defineConfig({ |
| | | presets: [ |
| | | // https://github.com/MellowCo/unocss-preset-weapp |
| | | presetWeapp(), |
| | | presetWeappAttributify(), |
| | | // https://unocss.dev/presets/icons |
| | | presetIcons({ |
| | | scale: 1.2, |
| | | warn: true, |
| | | extraProperties: { |
| | | display: "inline-block", |
| | | "vertical-align": "middle" |
| | | } |
| | | }) |
| | | ], |
| | | /** |
| | | * 自定义快捷语句 |
| | | * @see https://github.com/unocss/unocss#shortcuts |
| | | */ |
| | | shortcuts: { |
| | | "border-base": "border border-gray-500_10", |
| | | center: "flex justify-center items-center" |
| | | }, |
| | | theme: { |
| | | colors: { |
| | | // 主题颜色 |
| | | primary: "var(--theme-primary)", |
| | | success: "var(--theme-success)", |
| | | warning: "var(--theme-warning)", |
| | | error: "var(--theme-error)", |
| | | // 文字颜色 |
| | | "text-main": "var(--theme-main-color)", |
| | | "text-content": "var(--theme-content-color)", |
| | | "text-tips": "var(--theme-tips-color)", |
| | | "text-light": "var(--theme-light-color)", |
| | | "text-disabled": "var(--theme-disabled-color)", |
| | | // 背景颜色 |
| | | "bg-main": "var(--theme-bg-color)", |
| | | "bg-secondary": "var(--theme-bg-color-secondary)", |
| | | // 边框颜色 |
| | | "border-main": "var(--theme-border-color)" |
| | | } |
| | | }, |
| | | transformers: [ |
| | | // 启用 @apply 功能 |
| | | transformerDirectives({ |
| | | enforce: "pre" |
| | | }), |
| | | // https://unocss.dev/transformers/variant-group |
| | | // 启用 () 分组功能 |
| | | transformerVariantGroup(), |
| | | transformerAttributify(), |
| | | // https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerClass |
| | | transformerClass() |
| | | ] |
| | | }) |
| New file |
| | |
| | | import process from "node:process" |
| | | import { fileURLToPath, URL } from "node:url" |
| | | import { defineConfig, loadEnv } from "vite" |
| | | import { createViteProxy } from "./build/config/index" |
| | | import createVitePlugins from "./build/plugins/index" |
| | | import configEnv from "./src/config/env.js"; |
| | | |
| | | // https://vitejs.dev/config/ |
| | | export default defineConfig(({ command, mode }) => { |
| | | // mode: 区分生产环境还是开发环境 |
| | | console.log("command, mode -> ", command, mode) |
| | | |
| | | const { UNI_PLATFORM,UNI_CUSTOM_DEFINE } = process.env |
| | | const ENV_NAME = UNI_CUSTOM_DEFINE && JSON.parse(UNI_CUSTOM_DEFINE)?.ENV_NAME |
| | | const __APP_ENV__ = { |
| | | UNI_PLATFORM: UNI_PLATFORM, |
| | | ENV_NAME: ENV_NAME || 'development' |
| | | } |
| | | console.log("平台 -> ", __APP_ENV__.UNI_PLATFORM) // 得到 mp-weixin, h5, app 等 |
| | | console.log("环境 -> ", __APP_ENV__.ENV_NAME) // 得到 development,test 等 |
| | | |
| | | const env = loadEnv(mode, fileURLToPath(new URL("./env", import.meta.url))) |
| | | // console.log("环境变量 env -> ", env) |
| | | const isBuild = process.env.NODE_ENV === "production" |
| | | return { |
| | | define: { |
| | | __APP_ENV__, |
| | | }, |
| | | // 自定义env目录 |
| | | envDir: "./env", |
| | | resolve: { |
| | | // https://cn.vitejs.dev/config/#resolve-alias |
| | | alias: { |
| | | // 设置别名 |
| | | "@": fileURLToPath(new URL("./src", import.meta.url)) |
| | | } |
| | | }, |
| | | // vite 相关配置 |
| | | server: { |
| | | port: Number.parseInt(env.VITE_APP_PORT, 10), |
| | | hmr: true, |
| | | host: true, |
| | | open: true, |
| | | proxy: createViteProxy(env,__APP_ENV__.ENV_NAME) |
| | | }, |
| | | // 设置scss的api类型为modern-compiler |
| | | css: { |
| | | preprocessorOptions: { |
| | | scss: { |
| | | api: "modern-compiler", |
| | | // 消除一些不必要的警告 |
| | | silenceDeprecations: ["legacy-js-api"] |
| | | } |
| | | } |
| | | }, |
| | | plugins: createVitePlugins(isBuild), |
| | | esbuild: { |
| | | drop: JSON.parse(env.VITE_DROP_CONSOLE) ? ["console", "debugger"] : [] |
| | | } |
| | | } |
| | | }) |
| New file |
| | |
| | | # 告诉EditorConfig插件,这是根文件,不用继续往上查找 |
| | | root = true |
| | | |
| | | # 匹配全部文件 |
| | | [*] |
| | | # 设置字符集 |
| | | charset = utf-8 |
| | | # 缩进风格,可选space、tab |
| | | indent_style = space |
| | | # 缩进的空格数 |
| | | indent_size = 2 |
| | | # 结尾换行符,可选lf、cr、crlf |
| | | end_of_line = lf |
| | | # 在文件结尾插入新行 |
| | | insert_final_newline = true |
| | | # 删除一行中的前后空格 |
| | | trim_trailing_whitespace = true |
| | | |
| | | # 匹配md结尾的文件 |
| | | [*.md] |
| | | insert_final_newline = false |
| | | trim_trailing_whitespace = false |
| New file |
| | |
| | | # Logs |
| | | logs |
| | | *.log |
| | | npm-debug.log* |
| | | yarn-debug.log* |
| | | yarn-error.log* |
| | | pnpm-debug.log* |
| | | lerna-debug.log* |
| | | |
| | | node_modules |
| | | .DS_Store |
| | | dist |
| | | *.local |
| | | |
| | | # Editor directories and files |
| | | .idea |
| | | *.suo |
| | | *.ntvs* |
| | | *.njsproj |
| | | *.sln |
| | | *.sw? |
| | | |
| | | #user |
| | | .hbuilderx |
| | | unpackage |
| | | /stats.html |
| | | # pnpm-lock.yaml |
| | | yarn.lock |
| | | package-lock.json |
| New file |
| | |
| | | # 掌控智飞 |
| | | |
| | | ``` |
| | | npm install pnpm -g |
| | | pnpm install |
| | | pnpm run dev |
| | | |
| | | node:16.18.0 |
| | | npm:更换为淘宝镜像 |
| | | pnpm:8.6.12 |
| | | ``` |
| | | |
| | | # h5更新步骤 |
| | | |
| | | 打开软件,发行,自定义发行,选择对应的环境 |
| | | |
| | | 然后把代码拷贝到服务器上 |
| | | 测试 |
| | | /software/service/drone/web/work-wx |
| | | 正式 |
| | | /app/service/drone/web/work-wx |
| | | # app更新步骤 |
| | | |
| | | 修改 /src/config 里面的development的参数,改为对应环境的对应变量 |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | # uniapp 团队协作开发实践模板(Vue3) |
| | | |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | [](https://github.com/oyjt/uniapp-vue3-template) |
| | | |
| | | |
| | | 使用uniapp+vite+vue3+typescript+uview-plus+unocss 搭建的适合团队协作的快速开发模版 |
| | | |
| | | [uview-plus官方文档](https://uiadmin.net/uview-plus/) |
| | | |
| | | 本项目集众多项目的优点,打造最适合团队协作开发的项目模板。 |
| | | |
| | | 国内仓库地址:[https://gitee.com/ouyang/uniapp-vue3-template](https://gitee.com/ouyang/uniapp-vue3-template) |
| | | |
| | | 在线预览地址:[https://oyjt.github.io/uniapp-vue3-template/](https://oyjt.github.io/uniapp-vue3-template/) |
| | | |
| | | ### 特性 |
| | | |
| | | - [x] 集成`uview-plus3.0 ui`库 |
| | | - [x] 支持多环境打包构建 |
| | | - [x] 使用`pinia`状态管理 |
| | | - [x] 封装网络请求,并支持`Typescript` |
| | | - [x] 支持路径别名 |
| | | - [x] 支持自动加载组件和`API` |
| | | - [x] 自动校验`git`提交代码格式 |
| | | - [x] 集成`ESLint`、`StyleLint`、`EditorConfig`代码格式规范 |
| | | - [x] `Typescript`支持 |
| | | - [x] 集成`UnoCSS` |
| | | - [x] 集成`iconify`图标库 |
| | | - [x] 集成`z-paging`下拉刷新功能 |
| | | - [x] 添加页面跳转拦截,登录权限校验 |
| | | - [x] 支持`token`无感刷新 |
| | | - [x] 项目分包 |
| | | - [x] 集成小程序隐私协议授权组件 |
| | | - [x] 项目构建自动删除本地图片并替换本地图片路径为线上图片 |
| | | - [x] 集成包体积视图分析插件 |
| | | - [x] 支持国际化 |
| | | - [x] 集成`alova`网络请求(具体使用请切换到 [feature/alova](https://github.com/oyjt/uniapp-vue3-template/tree/feature/alova) 分支) |
| | | - [x] 集成`axios`网络请求(具体使用请切换到 [feature/axios](https://github.com/oyjt/uniapp-vue3-template/tree/feature/axios) 分支) |
| | | - [x] 支持新的`wot-design-uni`库(具体使用请切换到[feature/wot-design-uni](https://github.com/oyjt/uniapp-vue3-template/tree/feature/wot-design-uni)分支),[wot-design-uni官方文档](https://wot-design-uni.cn/) |
| | | - [x] 支持新的`shadcn-ui`库(具体使用请切换到[feature/shadcn-ui](https://github.com/oyjt/uniapp-vue3-template/tree/feature/shadcn-ui)分支),[shadcn-ui官方文档](https://ui.shadcn.com/) |
| | | - [x] 更好的 `AI` 支持,适配`cursor`和`trae`规则,集成`MCP`插件 |
| | | |
| | | ### uniapp插件推荐 |
| | | - [uniapp 插件精选(https://github.com/oyjt/awesome-uniapp)](https://github.com/oyjt/awesome-uniapp) |
| | | |
| | | ### 目录结构 |
| | | 项目中采用目前最新的技术方案来实现,目录结构清晰。 |
| | | ``` |
| | | uniapp-vue3-project |
| | | ├ build vite配置统一管理 |
| | | │ ├ config |
| | | │ └ plugins |
| | | ├ env 环境变量 |
| | | ├ scripts 一些脚本 |
| | | │ ├ post-upgrade.js 依赖库清理 |
| | | │ └ verify-commit.js git提交检验 |
| | | ├ src |
| | | │ ├ api 接口管理 |
| | | │ ├ components 公共组件 |
| | | │ ├ hooks 常用hooks封装 |
| | | │ ├ locale 国际化语言管理 |
| | | │ ├ pages 页面管理 |
| | | │ ├ plugins 插件管理 |
| | | │ ├ router 路由管理 |
| | | │ ├ static 静态资源 |
| | | │ ├ store 状态管理 |
| | | │ ├ utils 一些工具 |
| | | │ ├ App.vue |
| | | │ ├ main.ts |
| | | │ ├ manifest.json 项目配置 |
| | | │ ├ pages.json 页面配置 |
| | | │ └ uni.scss 全局scss变量 |
| | | ├ types 全局typescript类型文件 |
| | | │ ├ auto-imports.d.ts |
| | | │ ├ components.d.ts |
| | | │ ├ global.d.ts |
| | | │ └ module.d.ts |
| | | ├ LICENSE |
| | | ├ README.md |
| | | ├ cz.config.js cz-git配置 |
| | | ├ eslint.config.js eslint配置 |
| | | ├ index.html |
| | | ├ package.json |
| | | ├ pnpm-lock.yaml |
| | | ├ stylelint.config.js stylelint配置 |
| | | ├ tsconfig.json |
| | | ├ uno.config.ts unocss配置 |
| | | └ vite.config.ts vite配置 |
| | | ``` |
| | | |
| | | #### vite插件管理 |
| | | ``` |
| | | build |
| | | ├ config vite配置 |
| | | │ ├ index.ts 入口文件 |
| | | │ └ proxy.ts 跨域代理配置 |
| | | └ plugins vite插件 |
| | | ├ autoImport.ts 自动导入api |
| | | ├ cleanImage.ts 自动清理图片文件 |
| | | ├ component.ts 自动导入组件 |
| | | ├ index.ts 入口文件 |
| | | ├ replaceUrl.ts 自动替换图片地址为CDN地址 |
| | | ├ unocss.ts unocss配置 |
| | | └ visualizer.ts 包体积视图分析 |
| | | |
| | | ``` |
| | | |
| | | #### 接口管理 |
| | | ``` |
| | | api |
| | | ├ common 通用api |
| | | │ ├ index.ts |
| | | │ └ types.ts |
| | | ├ user 用户相关api |
| | | │ ├ index.ts |
| | | │ └ types.ts |
| | | └ index.ts 入口文件 |
| | | ``` |
| | | |
| | | #### hooks管理 |
| | | ``` |
| | | hooks |
| | | ├ use-clipboard 剪切板 |
| | | │ └ index.ts |
| | | ├ use-loading loading |
| | | │ └ index.ts |
| | | ├ use-modal 模态框 |
| | | │ └ index.ts |
| | | ├ use-permission 校验权限 |
| | | │ └ index.ts |
| | | ├ use-share 分享 |
| | | │ └ index.ts |
| | | └ index.ts 入口文件 |
| | | ``` |
| | | |
| | | ### 页面管理 |
| | | ``` |
| | | pages |
| | | ├ common 公共页面(分包common) |
| | | │ ├ login |
| | | │ │ └ index.vue |
| | | │ └ webview |
| | | │ └ index.vue |
| | | └ tab 主页面(主包) |
| | | ├ home |
| | | │ └ index.vue |
| | | ├ list |
| | | │ └ index.vue |
| | | └ user |
| | | └ index.vue |
| | | ``` |
| | | |
| | | #### 状态管理 |
| | | ``` |
| | | store |
| | | ├ modules |
| | | │ ├ app app状态 |
| | | │ │ ├ index.ts |
| | | │ │ └ types.ts |
| | | │ └ user 用户状态 |
| | | │ ├ index.ts |
| | | │ └ types.ts |
| | | └ index.ts 入口文件 |
| | | ``` |
| | | |
| | | ### 工具方法 |
| | | ``` |
| | | utils |
| | | ├ auth token相关方法 |
| | | │ └ index.ts |
| | | ├ common 通用方法 |
| | | │ └ index.ts |
| | | ├ modals 弹窗相关方法 |
| | | │ └ index.ts |
| | | ├ request 网络请求相关方法 |
| | | │ ├ index.ts |
| | | │ ├ interceptors.ts |
| | | │ ├ status.ts |
| | | │ └ types.ts |
| | | └ index.ts 入口文件 |
| | | ``` |
| | | |
| | | ### 使用方法 |
| | | |
| | | ```bash |
| | | # 安装依赖 |
| | | pnpm install |
| | | |
| | | # 启动H5 |
| | | pnpm dev:h5 |
| | | |
| | | # 启动微信小程序 |
| | | pnpm dev:mp-weixin |
| | | ``` |
| | | |
| | | ### 发布 |
| | | |
| | | ```bash |
| | | # 构建开发环境 |
| | | pnpm build:h5 |
| | | pnpm build:mp-weixin |
| | | |
| | | # 构建测试环境 |
| | | pnpm build:h5-test |
| | | pnpm build:mp-weixin-test |
| | | |
| | | # 构建生产环境 |
| | | pnpm build:h5-prod |
| | | pnpm build:mp-weixin-prod |
| | | ``` |
| | | |
| | | ### 更新uniapp版本 |
| | | |
| | | 更新uniapp相关依赖到最新正式版 |
| | | ```bash |
| | | pnpx @dcloudio/uvm@latest |
| | | ``` |
| | | 或者执行下面的命令 |
| | | ```bash |
| | | pnpm uvm |
| | | ``` |
| | | |
| | | 在升级完后,会自动添加很多无用依赖,执行下面的代码减小保体积 |
| | | ``` |
| | | pnpm uvm-rm |
| | | ``` |
| | | |
| | | ### `v3` 代码块 |
| | | 在 `vue` 文件中,输入 `v3` 按 `tab` 即可快速生成页面模板,可以大大加快页面生成。 |
| | | > 原理:基于 VSCode 代码块生成。 |
| | | |
| | | ### 登录鉴权 |
| | | 1. 页面如果需要登录才能访问,只需在 `pages.json` 文件中需要鉴权的页面下设置 `needLogin` 属性设置为 `true` 即可,比如 |
| | | ``` |
| | | { |
| | | "pages": [ |
| | | { |
| | | "path": "pages/test/test", |
| | | "needLogin": true, |
| | | "style": { |
| | | "navigationBarTitleText": "", |
| | | }, |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | 2. 如果有`tab`页面需要登录才能访问,上面的设置在小程序中点击`tabbar`时无效,因为在小程序中点击tabbar不会触发`uni.switchTab`方法,下面是官方给出的回复及解决方案。 |
| | | |
| | | > 拦截uni.switchTab本身没有问题。但是在微信小程序端点击tabbar的底层逻辑并不是触发uni.switchTab。所以误认为拦截无效,此类场景的解决方案是在tabbar页面的页面生命周期onShow中处理。 |
| | | |
| | | 可参考`pages/tab/user/index.vue`中的代码,核心代码如下: |
| | | ``` |
| | | <script setup lang="ts"> |
| | | // 引入鉴权hooks |
| | | import { usePermission } from "@/hooks"; |
| | | |
| | | onShow(async () => { |
| | | console.log("tabbar page onShow"); |
| | | const hasPermission = await usePermission(); |
| | | console.log(hasPermission ? "已登录" : "未登录,拦截跳转"); |
| | | }); |
| | | </script> |
| | | ``` |
| | | |
| | | ### 注意事项 |
| | | 1. 微信小程序开发者工具中内置的打包分析不准确,本项目使用了`rollup-plugin-visualizer`来分析小程序包体积,默认不开启,有需要的移除相关注释即可 |
| | | 2. 自动构建处理本地图片资源,使用了`vite-plugin-clean-build`和`vite-plugin-replace-image-url`这两个插件,默认不开启相关功能,如果需要使用再`build/vite/plugins/index.ts`文件中移除相关注释即可 |
| | | 3. 使用`vite-plugin-replace-image-url`插件,想要图片自动替换生效,需要在项目中使用绝对路径引入图片资源,如下示例所示。 |
| | | |
| | | 示例一:style中的图片使用 |
| | | ``` |
| | | <template> |
| | | <view :style="`background-image: url('${bgImg}')`"> |
| | | ... |
| | | </view> |
| | | </template> |
| | | <script setup lang="ts"> |
| | | import bgImg from '@/static/images/bg_img.png'; |
| | | </script> |
| | | ``` |
| | | |
| | | 示例二:js中的图片使用 |
| | | |
| | | ``` |
| | | <script setup lang="ts"> |
| | | import walletIcon from '@/static/images/icon_wallet.png'; |
| | | const menuList = [ |
| | | { |
| | | name: 'wallet', |
| | | title: '钱包', |
| | | icon: walletIcon, |
| | | }, |
| | | ... |
| | | ]; |
| | | </script> |
| | | ``` |
| | | |
| | | 示例二:css中的图片使用 |
| | | ``` |
| | | <style lang="scss"> |
| | | .icon { |
| | | background-image: url('@/static/images/icon.png') |
| | | } |
| | | </style> |
| | | ``` |
| | | |
| | | 4. 部分用户构建微信小程序如下错误,原因是微信开发者工具缺失了对应的依赖。 |
| | | ``` |
| | | This @babel/plugin-proposal-private-property-in-object version is not meant to |
| | | be imported. |
| | | ``` |
| | | 此时升级微信开发者工具,或者安装`@babel/plugin-proposal-private-property-in-object`依赖即可解决问题。 |
| | | |
| | | 5. `shadcn-ui` 分支采用最新的 `tailwindcss v4.1` 版本,因为现阶段的 `unocss` 对于最新版 `tailwindcss` 支持还不够完善。 |
| | | `shadcn-ui`并不太适合移动端使用,如果不喜欢可以移除,只保留纯净的框架。 |
| | | |
| New file |
| | |
| | | export * from './proxy' |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:40:50 |
| | | * @FilePath : \build\config\proxy.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import configEnv from "../../src/config/env.js"; |
| | | |
| | | export const createViteProxy = (env,envName = 'development') => { |
| | | const { VITE_APP_PROXY, VITE_API_PREFIX,VITE_APP_ENV } = env |
| | | // 不使用代理直接返回 |
| | | if (!JSON.parse(VITE_APP_PROXY)) return undefined |
| | | const proxy = { |
| | | [VITE_API_PREFIX]: { |
| | | target: configEnv?.[envName || VITE_APP_ENV]?.VITE_API_BASE_URL, |
| | | changeOrigin: true, |
| | | rewrite: path => path.replace(new RegExp(`^${VITE_API_PREFIX}`), ''), |
| | | }, |
| | | } |
| | | return proxy |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 14:51:32 |
| | | * @FilePath : \build\plugins\autoImport.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | /** |
| | | * @name AutoImportDeps |
| | | * @description 按需加载,自动引入 |
| | | */ |
| | | import AutoImport from 'unplugin-auto-import/vite' |
| | | |
| | | export const AutoImportDeps = () => { |
| | | return AutoImport({ |
| | | imports: ['vue', 'uni-app', 'pinia'], |
| | | // 禁用生成 .d.ts 文件,因为项目已转为 JavaScript |
| | | dts: false, |
| | | vueTemplate: true, |
| | | }) |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name cleanImagePlugin |
| | | * @description 清除构建后的图片资源 |
| | | */ |
| | | import CleanBuild from "vite-plugin-clean-build" |
| | | |
| | | export const CleanImagePlugin = () => { |
| | | return CleanBuild({ |
| | | outputDir: "dist/build/mp-weixin", |
| | | patterns: [ |
| | | "static/images/**", |
| | | "!static/images/logo.png", |
| | | "!static/images/tabbar/**" |
| | | ] |
| | | }) |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name AutoRegistryComponents |
| | | * @description 按需加载,自动引入 |
| | | */ |
| | | import Components from 'unplugin-vue-components/vite' |
| | | |
| | | export const AutoRegistryComponents = () => { |
| | | return Components({ |
| | | // 禁用生成 .d.ts 文件,因为项目已转为 JavaScript |
| | | dts: false, |
| | | }) |
| | | } |
| New file |
| | |
| | | import uniPlugin from '@dcloudio/vite-plugin-uni' |
| | | import ViteRestart from 'vite-plugin-restart' |
| | | import { AutoImportDeps } from './autoImport' |
| | | // import { ConfigImageminPlugin } from './imagemin'; |
| | | // import { ReplaceUrlPlugin } from './replaceUrl'; |
| | | import { AutoRegistryComponents } from './component' |
| | | import { MCPPlugin } from './mcp' |
| | | import { ConfigUnoCSSPlugin } from './unocss' |
| | | export default function createVitePlugins (isBuild) { |
| | | const vitePlugins = [ |
| | | // UnoCSS配置 |
| | | ConfigUnoCSSPlugin(), |
| | | // 自动按需引入依赖 |
| | | AutoImportDeps(), |
| | | // 自动按需引入组件(注意:需注册至 uni 之前,否则不会生效) |
| | | AutoRegistryComponents(), |
| | | // uni支持(兼容性写法,当type为module时,必须要这样写) |
| | | uniPlugin.default(), |
| | | ViteRestart({ |
| | | // 通过这个插件,在修改vite.config.js文件则不需要重新运行也生效配置 |
| | | restart: ['vite.config.js'], |
| | | }), |
| | | // 为项目开启 MCP Server |
| | | MCPPlugin(), |
| | | ] |
| | | |
| | | if (isBuild) { |
| | | const buildPlugins = [ |
| | | // 图片资源自动转换为网络资源 |
| | | // ReplaceUrlPlugin(), |
| | | // 自动清除本地图片 |
| | | // CleanImagePlugin(), |
| | | // 打包视图分析 |
| | | // VisualizerPlugin(), |
| | | ] |
| | | vitePlugins.push(...buildPlugins) |
| | | } |
| | | |
| | | return vitePlugins |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name MCPPlugin |
| | | * @description MCP服务 |
| | | */ |
| | | import { VueMcp } from "vite-plugin-vue-mcp" |
| | | |
| | | export const MCPPlugin = () => { |
| | | return VueMcp() |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name ReplaceImageUrl |
| | | * @description 替换图片地址 |
| | | */ |
| | | import replaceImageUrl from 'vite-plugin-replace-image-url' |
| | | |
| | | export const ReplaceUrlPlugin = () => { |
| | | return replaceImageUrl({ |
| | | publicPath: 'https://photo.example.com/miniprogram', |
| | | sourceDir: 'src/static', |
| | | verbose: true, |
| | | }) |
| | | } |
| New file |
| | |
| | | /** |
| | | * @name ConfigUnoCSSPlugin |
| | | * @description UnoCSS相关配置 |
| | | */ |
| | | import UnoCSS from 'unocss/vite' |
| | | |
| | | export const ConfigUnoCSSPlugin = () => { |
| | | return UnoCSS() |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:42:33 |
| | | * @FilePath : \build\plugins\visualizer.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | /** |
| | | * @name VisualizerPlugin |
| | | * @description 打包视图分析 |
| | | */ |
| | | import { visualizer } from 'rollup-plugin-visualizer' |
| | | |
| | | export const VisualizerPlugin = () => { |
| | | return visualizer({ |
| | | emitFile: false, |
| | | filename: 'stats.html', // 分析图生成的文件名 |
| | | open: true, // 如果存在本地服务端口,将在打包后自动展示 |
| | | }) |
| | | } |
| New file |
| | |
| | | /** @type {import('cz-git').CommitizenGitOptions} */ |
| | | export default { |
| | | alias: { fd: 'docs: fix typos' }, |
| | | messages: { |
| | | type: '选择你要提交的类型 :', |
| | | scope: '选择一个提交范围(可选):', |
| | | customScope: '请输入自定义的提交范围 :', |
| | | subject: '填写简短精炼的变更描述 :\n', |
| | | body: '填写更加详细的变更描述(可选)。使用 \'|\' 换行 :\n', |
| | | breaking: '列举非兼容性重大的变更(可选)。使用 \'|\' 换行 :\n', |
| | | footerPrefixesSelect: '选择关联issue前缀(可选):', |
| | | customFooterPrefix: '输入自定义issue前缀 :', |
| | | footer: '列举关联issue (可选) 例如: #31, #I3244 :\n', |
| | | confirmCommit: '是否提交或修改commit ?', |
| | | }, |
| | | types: [ |
| | | { value: 'feat', name: 'feat: 新增功能 | A new feature', emoji: ':sparkles:' }, |
| | | { value: 'fix', name: 'fix: 修复缺陷 | A bug fix', emoji: ':bug:' }, |
| | | { value: 'docs', name: 'docs: 文档更新 | Documentation only changes', emoji: ':memo:' }, |
| | | { value: 'style', name: 'style: 代码格式 | Changes that do not affect the meaning of the code', emoji: ':lipstick:' }, |
| | | { value: 'refactor', name: 'refactor: 代码重构 | A code change that neither fixes a bug nor adds a feature', emoji: ':recycle:' }, |
| | | { value: 'perf', name: 'perf: 性能提升 | A code change that improves performance', emoji: ':zap:' }, |
| | | { value: 'test', name: 'test: 测试相关 | Adding missing tests or correcting existing tests', emoji: ':white_check_mark:' }, |
| | | { value: 'build', name: 'build: 构建相关 | Changes that affect the build system or external dependencies', emoji: ':package:' }, |
| | | { value: 'ci', name: 'ci: 持续集成 | Changes to our CI configuration files and scripts', emoji: ':ferris_wheel:' }, |
| | | { value: 'chore', name: 'chore: 其他修改 | Other changes that don\'t modify src or test files', emoji: ':hammer:' }, |
| | | { value: 'revert', name: 'revert: 回退代码 | Reverts a previous commit', emoji: ':rewind:' }, |
| | | ], |
| | | useEmoji: false, |
| | | emojiAlign: 'center', |
| | | useAI: false, |
| | | aiNumber: 1, |
| | | themeColorCode: '', |
| | | scopes: [], |
| | | allowCustomScopes: true, |
| | | allowEmptyScopes: true, |
| | | customScopesAlign: 'bottom', |
| | | customScopesAlias: 'custom', |
| | | emptyScopesAlias: 'empty', |
| | | upperCaseSubject: false, |
| | | markBreakingChangeMode: false, |
| | | allowBreakingChanges: ['feat', 'fix'], |
| | | breaklineNumber: 100, |
| | | breaklineChar: '|', |
| | | skipQuestions: [], |
| | | issuePrefixes: [{ value: 'closed', name: 'closed: 标记 ISSUES 已完成' }], |
| | | customIssuePrefixAlign: 'top', |
| | | emptyIssuePrefixAlias: 'skip', |
| | | customIssuePrefixAlias: 'custom', |
| | | allowCustomIssuePrefix: true, |
| | | allowEmptyIssuePrefix: true, |
| | | confirmColorize: true, |
| | | minSubjectLength: 0, |
| | | defaultBody: '', |
| | | defaultIssues: '', |
| | | defaultScope: '', |
| | | defaultSubject: '', |
| | | } |
| New file |
| | |
| | | # 页面标题 |
| | | VITE_APP_TITLE=uniapp-vue3模板项目 |
| | | |
| | | # 开发环境配置 |
| | | VITE_APP_ENV=development |
| | | |
| | | # 端口号 |
| | | VITE_APP_PORT=9527 |
| | | |
| | | # h5是否需要配置代理 |
| | | VITE_APP_PROXY=true |
| | | |
| | | # API代理前缀 |
| | | VITE_API_PREFIX=/api |
| | | |
| | | # 删除console |
| | | VITE_DROP_CONSOLE=false |
| New file |
| | |
| | | # 开发环境配置 |
| | | VITE_APP_ENV=development |
| | | |
| | | # 删除console |
| | | VITE_DROP_CONSOLE=false |
| New file |
| | |
| | | # 生产环境配置 |
| | | VITE_APP_ENV=production |
| | | |
| | | # 删除console |
| | | VITE_DROP_CONSOLE=false |
| New file |
| | |
| | | import antfu from '@antfu/eslint-config' |
| | | |
| | | export default antfu( |
| | | { |
| | | unocss: true, |
| | | node: true, |
| | | ignores: [ |
| | | 'dist/**', |
| | | '.vscode/**', |
| | | '.idea/**', |
| | | 'node_modules/**', |
| | | 'src/uni_modules/**', |
| | | 'src/manifest.json', |
| | | 'src/pages.json', |
| | | 'README.md', |
| | | ], |
| | | }, |
| | | { |
| | | rules: { |
| | | // vue顶级标签的顺序 |
| | | 'vue/block-order': ['error', { |
| | | order: ['template', 'script', 'style'], |
| | | }], |
| | | // 不需要尾随逗号 |
| | | 'comma-dangle': ['error', 'never'], |
| | | // 允许console |
| | | 'no-console': 'off', |
| | | // 不需要分号 |
| | | 'style/semi': ['error', 'never'], |
| | | // 块内的空行 |
| | | 'padded-blocks': ['error', 'never'], |
| | | // 顶级函数应使用 function 关键字声明 |
| | | 'antfu/top-level-function': 'off', |
| | | // 全局的 process 不能用 |
| | | 'node/prefer-global/process': 'off', |
| | | // 禁止未使用的捕获组 |
| | | 'regexp/no-unused-capturing-group': 'off', |
| | | // 允许接口和类型别名中的成员之间不使用分隔符 |
| | | 'style/member-delimiter-style': ['error', { |
| | | multiline: { |
| | | delimiter: 'none', |
| | | requireLast: false, |
| | | }, |
| | | singleline: { |
| | | delimiter: 'none', |
| | | requireLast: false, |
| | | }, |
| | | multilineDetection: 'brackets', |
| | | }], |
| | | // if 语句后需要换行 |
| | | 'antfu/if-newline': 'off', |
| | | }, |
| | | }, |
| | | ) |
| New file |
| | |
| | | <!DOCTYPE html> |
| | | <html lang="zh-CN"> |
| | | <head> |
| | | <meta charset="UTF-8" /> |
| | | <script> |
| | | var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
| | | CSS.supports('top: constant(a)')) |
| | | document.write( |
| | | '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
| | | (coverSupport ? ', viewport-fit=cover' : '') + '" />') |
| | | </script> |
| | | <title></title> |
| | | <!--preload-links--> |
| | | <!--app-context--> |
| | | </head> |
| | | <body> |
| | | <div id="app"><!--app-html--></div> |
| | | <script type="module" src="/src/main.js"></script> |
| | | </body> |
| | | </html> |
| New file |
| | |
| | | { |
| | | "name": "work-wx", |
| | | "type": "module", |
| | | "version": "1.5.0", |
| | | "description": "掌控智飞", |
| | | "private": true, |
| | | "author": { |
| | | "name": "ztzf" |
| | | }, |
| | | "license": "MIT", |
| | | "homepage": "https://github.com/oyjt/uniapp-vue3-template", |
| | | "repository": { |
| | | "type": "git", |
| | | "url": "https://github.com/oyjt/uniapp-vue3-template.git" |
| | | }, |
| | | "keywords": [], |
| | | "scripts": { |
| | | "preinstall": "npx only-allow pnpm", |
| | | "uvm": "npx @dcloudio/uvm@latest", |
| | | "uvm-rm": "node ./scripts/post-upgrade.js", |
| | | "dev:h5": "uni", |
| | | "dev:h5:ssr": "uni --ssr", |
| | | "dev:h5-test": "uni --mode test", |
| | | "dev:h5-pro": "uni --mode production", |
| | | "dev:mp-weixin": "uni -p mp-weixin", |
| | | "dev:mp-weixin-test": "uni -p mp-weixin --mode test", |
| | | "dev:mp-weixin-prod": "uni -p mp-weixin --mode production", |
| | | "dev:app": "uni -p app", |
| | | "dev:app-android": "uni -p app-android", |
| | | "dev:app-ios": "uni -p app-ios", |
| | | "build:h5": "uni build", |
| | | "build:h5:ssr": "uni build --ssr", |
| | | "build:h5-test": "uni build --mode test", |
| | | "build:h5-prod": "uni build --mode production", |
| | | "build:mp-weixin": "uni build -p mp-weixin", |
| | | "build:mp-weixin-test": "uni build -p mp-weixin --mode test", |
| | | "build:mp-weixin-prod": "uni build -p mp-weixin --mode production", |
| | | "build:app": "uni build -p app", |
| | | "build:app-android": "uni build -p app-android", |
| | | "build:app-ios": "uni build -p app-ios", |
| | | "eslint": "eslint \"src/**/*.{js,jsx,ts,tsx,vue}\"", |
| | | "eslint:fix": "eslint \"src/**/*.{js,jsx,ts,tsx,vue}\" --fix", |
| | | "stylelint": "stylelint \"src/**/*.{vue,scss,css,sass,less}\"", |
| | | "stylelint:fix": "stylelint \"src/**/*.{vue,scss,css,sass,less}\" --fix", |
| | | "cz": "git add . && npx czg", |
| | | "clean": "npx rimraf node_modules", |
| | | "clean:cache": "npx rimraf node_modules/.cache" |
| | | }, |
| | | "dependencies": { |
| | | "@dcloudio/uni-app": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-app-harmony": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-app-plus": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-components": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-h5": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-alipay": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-baidu": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-harmony": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-jd": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-kuaishou": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-lark": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-qq": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-toutiao": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-weixin": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-mp-xhs": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-quickapp-webview": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-ui": "^1.5.11", |
| | | "dayjs": "^1.11.18", |
| | | "js-audio-recorder": "^1.0.7", |
| | | "js-base64": "^3.7.4", |
| | | "js-md5": "^0.7.3", |
| | | "leaflet": "^1.9.4", |
| | | "deep-pick-omit": "1.2.1", |
| | | "destr": "2.0.5", |
| | | "pinia": "2.2.4", |
| | | "pinia-plugin-persistedstate": "4.1.3", |
| | | "trtc-sdk-v5": "^5.14.1", |
| | | "uview-plus": "^3.5.41", |
| | | "vue": "3.4.21", |
| | | "vue-i18n": "9.1.9", |
| | | "z-paging": "^2.8.8" |
| | | }, |
| | | "devDependencies": { |
| | | "@antfu/eslint-config": "5.0.0", |
| | | "@dcloudio/uni-automator": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-cli-shared": "3.0.0-4070520250711001", |
| | | "@dcloudio/uni-stacktracey": "3.0.0-4070520250711001", |
| | | "@dcloudio/vite-plugin-uni": "3.0.0-4070520250711001", |
| | | "@esbuild/darwin-arm64": "0.25.1", |
| | | "@esbuild/darwin-x64": "0.25.1", |
| | | "@iconify-json/mdi": "^1.2.3", |
| | | "@rollup/rollup-darwin-arm64": "4.38.0", |
| | | "@rollup/rollup-darwin-x64": "4.38.0", |
| | | "@unocss/eslint-plugin": "^66.3.3", |
| | | "@unocss/preset-icons": "^66.3.3", |
| | | "@vue/runtime-core": "^3.4.21", |
| | | "czg": "^1.12.0", |
| | | "eslint": "^9.32.0", |
| | | "lint-staged": "^16.1.6", |
| | | "miniprogram-api-typings": "^4.1.0", |
| | | "picocolors": "^1.1.1", |
| | | "rimraf": "^6.0.1", |
| | | "rollup-plugin-visualizer": "^6.0.3", |
| | | "sass": "1.79.6", |
| | | "sass-loader": "^16.0.4", |
| | | "stylelint": "^16.23.0", |
| | | "stylelint-config-recess-order": "^6.1.0", |
| | | "stylelint-config-standard": "^39.0.0", |
| | | "stylelint-config-standard-vue": "^1.0.0", |
| | | "unocss": "65.5.0", |
| | | "unocss-preset-weapp": "^66.0.2", |
| | | "unplugin-auto-import": "19.3.0", |
| | | "unplugin-vue-components": "^28.8.0", |
| | | "vite": "5.2.8", |
| | | "vite-plugin-clean-build": "^1.4.1", |
| | | "vite-plugin-replace-image-url": "^1.4.1", |
| | | "vite-plugin-restart": "^1.0.0", |
| | | "vite-plugin-vue-mcp": "^0.3.2" |
| | | }, |
| | | "lint-staged": { |
| | | "src/**/*.{js,jsx}": "eslint --fix", |
| | | "*.{scss,css,style,html}": "stylelint --fix", |
| | | "*.vue": [ |
| | | "eslint --fix", |
| | | "stylelint --fix" |
| | | ] |
| | | }, |
| | | "uni-app": { |
| | | "scripts": { |
| | | "h5-dev": { |
| | | "title": "H5 开发环境", |
| | | "env": { |
| | | "UNI_PLATFORM": "h5", |
| | | "ENV_NAME": "development" |
| | | } |
| | | }, |
| | | "h5-test": { |
| | | "title": "H5 测试环境", |
| | | "env": { |
| | | "UNI_PLATFORM": "h5", |
| | | "ENV_NAME": "test" |
| | | } |
| | | }, |
| | | "h5-prod": { |
| | | "title": "H5 生产环境", |
| | | "env": { |
| | | "UNI_PLATFORM": "h5", |
| | | "ENV_NAME": "production" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "setting": { |
| | | "es6": true, |
| | | "postcss": true, |
| | | "minified": true, |
| | | "uglifyFileName": false, |
| | | "enhance": true, |
| | | "packNpmRelationList": [], |
| | | "babelSetting": { |
| | | "ignore": [], |
| | | "disablePlugins": [], |
| | | "outputPath": "" |
| | | }, |
| | | "useCompilerPlugins": false, |
| | | "minifyWXML": true |
| | | }, |
| | | "compileType": "miniprogram", |
| | | "simulatorPluginLibVersion": {}, |
| | | "packOptions": { |
| | | "ignore": [], |
| | | "include": [] |
| | | }, |
| | | "appid": "wxf7a7651c306981af", |
| | | "editorSetting": {} |
| | | } |
| New file |
| | |
| | | { |
| | | "libVersion": "3.9.1", |
| | | "projectname": "work-wx", |
| | | "setting": { |
| | | "urlCheck": true, |
| | | "coverView": true, |
| | | "lazyloadPlaceholderEnable": false, |
| | | "skylineRenderEnable": false, |
| | | "preloadBackgroundData": false, |
| | | "autoAudits": false, |
| | | "showShadowRootInWxmlPanel": true, |
| | | "compileHotReLoad": true |
| | | } |
| | | } |
| New file |
| | |
| | | // # 执行 `pnpm upgrade` 后会升级 `uniapp` 相关依赖 |
| | | // # 在升级完后,会自动添加很多无用依赖,这需要删除以减小依赖包体积 |
| | | // # 只需要执行下面的命令即可 |
| | | |
| | | import { exec } from 'node:child_process' |
| | | |
| | | // 定义要执行的命令 |
| | | const dependencies = [ |
| | | '@dcloudio/uni-app-harmony', |
| | | // TODO: 如果需要某个平台的小程序,请手动删除或注释掉 |
| | | '@dcloudio/uni-mp-alipay', |
| | | '@dcloudio/uni-mp-baidu', |
| | | '@dcloudio/uni-mp-jd', |
| | | '@dcloudio/uni-mp-kuaishou', |
| | | '@dcloudio/uni-mp-lark', |
| | | '@dcloudio/uni-mp-qq', |
| | | '@dcloudio/uni-mp-toutiao', |
| | | '@dcloudio/uni-mp-xhs', |
| | | '@dcloudio/uni-quickapp-webview', |
| | | '@dcloudio/uni-mp-harmony', |
| | | // vue 已经内置了 @vue/runtime-core,这里移除掉 |
| | | '@vue/runtime-core', |
| | | ] |
| | | |
| | | // 使用exec执行命令 |
| | | exec(`pnpm remove ${dependencies.join(' ')}`, (error, stdout, stderr) => { |
| | | if (error) { |
| | | // 如果有错误,打印错误信息 |
| | | console.error(`执行出错: ${error}`) |
| | | return |
| | | } |
| | | // 打印正常输出 |
| | | console.log(`stdout: ${stdout}`) |
| | | // 如果有错误输出,也打印出来 |
| | | console.error(`stderr: ${stderr}`) |
| | | }) |
| New file |
| | |
| | | <script setup> |
| | | import { onHide, onLaunch, onShow } from "@dcloudio/uni-app"; |
| | | import { useAppStore, useUserStore } from "@/store"; |
| | | import { useGlobalWS } from "@/hooks/useGlobalWS.js"; |
| | | |
| | | const appStore = useAppStore(); |
| | | const userStore = useUserStore(); |
| | | |
| | | useGlobalWS(); |
| | | |
| | | onShow(() => { |
| | | console.log("App Show"); |
| | | }); |
| | | |
| | | onHide(() => { |
| | | console.log("App Hide"); |
| | | }); |
| | | |
| | | onLaunch(() => { |
| | | // 初始化系统信息 |
| | | appStore.initSystemInfo(); |
| | | if (!userStore.userInfo) { |
| | | //不存在则跳转至登录页 |
| | | uni.reLaunch({ |
| | | url: "/pages/login/index", |
| | | }); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | /* 每个页面公共css */ |
| | | @import "uview-plus/index.scss"; |
| | | @import "@/static/styles/common.scss"; |
| | | |
| | | .TUICallKit-mobile { |
| | | position: fixed; |
| | | left: 0; |
| | | top: 0; |
| | | z-index: 9999; |
| | | } |
| | | |
| | | page { |
| | | background-image: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/bg.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | background-attachment: fixed; |
| | | // min-height: 10vh; |
| | | } |
| | | |
| | | .uni-tabbar-border { |
| | | background-color: #f6f6f6 !important; |
| | | } |
| | | |
| | | .uni-page-head__title { |
| | | font-family: Source Han Sans CN, Source Han Sans CN !important; |
| | | font-weight: 400 !important; |
| | | font-size: 17px !important; |
| | | color: #222324 !important; |
| | | } |
| | | |
| | | .uni-page-head { |
| | | background: transparent !important; |
| | | } |
| | | </style> |
| New file |
| | |
| | | import { post, upload } from '@/utils/request' |
| | | |
| | | // 文件上传 |
| | | export const uploadFile = filePath => |
| | | upload('/common/upload', { filePath, name: 'file' }) |
| | | |
| | | // 发送验证码 |
| | | export const sendCode = data => post('/sendCode', { data }) |
| New file |
| | |
| | | import {request} from "@/utils/request" |
| | | |
| | | export const startVoice = data => { |
| | | return request({ |
| | | url: `/drone-device-core/speak/api/v1/startVoice`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | |
| | | // 上传音频文件 |
| | | export const uploadSpeak = data => { |
| | | return request({ |
| | | url:'/drone-device-core/speak/api/v1/uploadSpeak', |
| | | method: 'post', |
| | | headers: { |
| | | 'Content-Type': 'multipart/form-data', |
| | | }, |
| | | data, |
| | | }) |
| | | } |
| New file |
| | |
| | | import {request} from "@/utils/index.js"; |
| | | |
| | | export const getJobListApi = (data, params) => { |
| | | return request({ |
| | | url: `/drone-device-core/wayline/waylineJobInfo/jobList`, |
| | | method: 'post', |
| | | data, |
| | | params, |
| | | }) |
| | | } |
| New file |
| | |
| | | import {request} from "@/utils/request" |
| | | |
| | | export const getDeviceRegionApi = data => { |
| | | return request({ |
| | | url: '/drone-device-core/manage/api/v1/devices/getDeviceRegion', |
| | | method: 'post', |
| | | data: { hidden_flag: 0, ...data }, |
| | | }) |
| | | } |
| New file |
| | |
| | | import { |
| | | get, |
| | | post, |
| | | request |
| | | } from "@/utils/request" |
| | | |
| | | import website from '@/config/website' |
| | | |
| | | /** 登录 */ |
| | | export const login = data => |
| | | post("/user/login", { |
| | | data, |
| | | custom: { |
| | | auth: false |
| | | } |
| | | }) |
| | | |
| | | /** 验证码登录 */ |
| | | export const loginByCode = data => post("/user/loginByCode", { |
| | | data |
| | | }) |
| | | |
| | | /** 退出登录 */ |
| | | export const logout = () => post("/user/logout") |
| | | |
| | | // 用户登录接口 |
| | | export const loginByUsername = (tenantId, deptId, roleId, username, password, type, key, code) => { |
| | | return request({ |
| | | url: '/blade-auth/oauth/token', |
| | | method: 'post', |
| | | header: { |
| | | 'Tenant-Id': tenantId, |
| | | 'Dept-Id': website.switchMode ? deptId : '', |
| | | 'Role-Id': website.switchMode ? roleId : '', |
| | | 'Captcha-Key': key, |
| | | 'Captcha-Code': code, |
| | | }, |
| | | params: { |
| | | tenantId, |
| | | username, |
| | | password, |
| | | grant_type: 'password', |
| | | scope: 'all', |
| | | type, |
| | | }, |
| | | }) |
| | | } |
| | | export const getUserInfo = () => { |
| | | return request({ |
| | | url: '/blade-system/user/info', |
| | | method: 'get', |
| | | }); |
| | | }; |
| | | export const updateInfo = row => { |
| | | return request({ |
| | | url: '/blade-system/user/update-info', |
| | | method: 'post', |
| | | data: row, |
| | | }); |
| | | }; |
| | | export const updatePassword = (oldPassword, newPassword, newPassword1) => { |
| | | return request({ |
| | | url: '/blade-system/user/update-password', |
| | | method: 'post', |
| | | params: { |
| | | oldPassword, |
| | | newPassword, |
| | | newPassword1, |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 发送通话信息 |
| | | export const sendVoiceCallApi = (data) => { |
| | | return request({ |
| | | url: `/drone-device-core/dp/call/sendVoiceCall`, |
| | | method: 'post', |
| | | data |
| | | }) |
| | | } |
| New file |
| | |
| | | import {request} from "@/utils/index.js"; |
| | | export const getList = (data) => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/eventPage', |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | } |
| | | // 获取状态统计数据 |
| | | export const getstatusCount = (params) => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/getstatusCount', |
| | | method: 'get', |
| | | params, |
| | | }) |
| | | } |
| | | |
| | | export const getStepInfo = (eventNum) => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/getStepInfo', |
| | | method: 'get', |
| | | params: { eventNum } |
| | | }) |
| | | } |
| | | |
| | | // 修改接口:处理待审核状态,动态构建 FormData 提交 |
| | | export const flowEvent = (data, file) => { |
| | | const formData = new FormData() |
| | | |
| | | // 动态添加非空字段到 FormData |
| | | Object.entries(data).forEach(([key, value]) => { |
| | | if (value !== undefined && value !== null) { |
| | | formData.append(key, value) |
| | | } |
| | | }) |
| | | |
| | | // 如果 file 存在,则添加到 FormData |
| | | if (file) { |
| | | formData.append('file', file) |
| | | } |
| | | for (let [key, value] of formData.entries()) { |
| | | console.log(key, value) |
| | | } |
| | | console.log('formData',formData) |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/flowEvent', |
| | | method: 'post', |
| | | data: formData, |
| | | headers: { |
| | | 'Content-Type': 'multipart/form-data', // 设置为表单数据格式 |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | // 新增接口:获取工单详细信息 |
| | | export const getTicketInfo = (id) => { |
| | | return request({ |
| | | url: '/drone-device-core/jobEvent/getTicketInfo', |
| | | method: 'get', |
| | | params: { id }, // 使用工单 ID 查询 |
| | | }) |
| | | } |
| New file |
| | |
| | | <template> |
| | | <web-view :src="src" @message="viewMessage" :allow="allow"/> |
| | | </template> |
| | | |
| | | |
| | | <script setup> |
| | | |
| | | |
| | | const allow = "accelerometer;ambient-light-sensor;autoplay;battery;camera;clipboard-read;clipboard-write;cross-origin-isolated;display-capture;document-domain;encrypted-media;execution-while-not-rendered;execution-while-out-of-viewport;fullscreen;gamepad;geolocation;gyroscope;hid;idle-detection;local-fonts;magnetometer;microphone;midi;payment;picture-in-picture;publickey-credentials-get;screen-wake-lock;serial;speaker-selection;storage-access;sync-xhr;usb;web-share;xr-spatial-tracking" |
| | | const src = defineModel("src"); |
| | | const emit = defineEmits(["webMessage"]); |
| | | |
| | | function viewMessage(event) { |
| | | messageFun({ |
| | | data: { |
| | | data: { |
| | | arg: event.detail.data[0], |
| | | }, |
| | | type: "WEB_INVOKE_APPSERVICE", |
| | | }, |
| | | }); |
| | | } |
| | | |
| | | // WEB_INVOKE_APPSERVICE |
| | | function messageFun(e) { |
| | | if (e.data.type === "WEB_INVOKE_APPSERVICE") { |
| | | if (e.data.data.arg.type === "tokenExpired") { |
| | | return uni.reLaunch({ |
| | | url: "/pages/login/index", |
| | | }); |
| | | } |
| | | emit("webMessage", e.data.data.arg); |
| | | } |
| | | } |
| | | |
| | | |
| | | onLoad((obj) => { |
| | | // const h5Params = obj?.cs && JSON.parse(obj?.cs) |
| | | // console.log('h5Params', h5Params) |
| | | // h5Params && viewMessage({detail: {data: [h5Params.data]}}) |
| | | }) |
| | | |
| | | onShow(() => { |
| | | if (window && window.addEventListener) |
| | | window.addEventListener("message", messageFun); |
| | | }); |
| | | onHide(() => { |
| | | if (window && window.removeEventListener) |
| | | window.removeEventListener("message", messageFun); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | <template> |
| | | <u-popup :show="modelValue" round="20" @close="closeAgreePrivacy"> |
| | | <view class="p-30rpx"> |
| | | <view class="text-lg text-black font-bold"> |
| | | <span>{{ initTitle }}</span> |
| | | </view> |
| | | |
| | | <view class="flex flex-col"> |
| | | <span class="pt-30rpx text-black font-bold">{{ initSubTitle }}</span> |
| | | <span class="pt-30rpx text-sm text-black" |
| | | >1.为向您提供基本的服务,我们会遵循正当、合法、必要的原则收集和使用必要的信息。</span |
| | | > |
| | | <span class="pt-30rpx text-sm text-black" |
| | | >2.基于您的授权我们可能会收集和使用您的相关信息,您有权拒绝或取消授权。</span |
| | | > |
| | | <span class="pt-30rpx text-sm text-black" |
| | | >3.未经您的授权同意,我们不会将您的信息共享给第三方或用于您未授权的其他用途。</span |
| | | > |
| | | <span class="pt-30rpx text-sm text-black" |
| | | >4.详细信息请您完整阅读<text |
| | | class="text-decoration" |
| | | @click="openPrivacyContract" |
| | | >{{ initPrivacyContractName }}</text |
| | | ></span |
| | | > |
| | | </view> |
| | | |
| | | <view class="mt-30rpx flex items-center justify-around pt-10rpx"> |
| | | <view class="min-w-100px"> |
| | | <button class="button button-default" @click="disagree">拒绝</button> |
| | | </view> |
| | | <view class="min-w-100px"> |
| | | <button |
| | | :id="agreePrivacyId" |
| | | class="button button-primary" |
| | | open-type="agreePrivacyAuthorization" |
| | | @agreeprivacyauthorization="agree" |
| | | > |
| | | 同意 |
| | | </button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </u-popup> |
| | | </template> |
| | | |
| | | <script setup> |
| | | const props = withDefaults(defineProps(), { |
| | | modelValue: false, |
| | | title: "", |
| | | subTitle: "", |
| | | disableCheckPrivacy: true, |
| | | agreePrivacyId: "agree-btn", |
| | | }); |
| | | |
| | | const emit = defineEmits([ |
| | | "update:modelValue", |
| | | "needPrivacyAuthorization", |
| | | "agree", |
| | | "disagree", |
| | | ]); |
| | | // 初始化的标题 |
| | | const initTitle = ref("隐私政策概要"); |
| | | // 初始化的副标题 |
| | | const initSubTitle = ref(""); |
| | | // 隐私政策 |
| | | const initPrivacyContractName = ref("隐私政策"); |
| | | |
| | | // 打开隐私 |
| | | function openAgreePrivacy() { |
| | | emit("update:modelValue", true); |
| | | } |
| | | |
| | | // 关闭隐私 |
| | | function closeAgreePrivacy() { |
| | | emit("update:modelValue", false); |
| | | } |
| | | |
| | | // 需要初始化的数据 |
| | | function initData() { |
| | | initTitle.value = props.title || initTitle.value; |
| | | initSubTitle.value = |
| | | props.subTitle || |
| | | `亲爱的用户,感谢您一直以来的支持!为了更好地保护您的权益,同时遵守相关监管要求,请认真阅读${initPrivacyContractName.value},特向您说明如下:`; |
| | | } |
| | | |
| | | // 检测是否授权 |
| | | function checkPrivacySetting() { |
| | | wx.getPrivacySetting({ |
| | | success: (res) => { |
| | | // 未授权弹框 |
| | | if (res.needAuthorization) { |
| | | initPrivacyContractName.value = res.privacyContractName; |
| | | initData(); |
| | | // 是否禁用 自动检测隐私并弹框 |
| | | if (!props.disableCheckPrivacy) { |
| | | // 需要弹出隐私协议 |
| | | openAgreePrivacy(); |
| | | } |
| | | } else { |
| | | // 用户已经同意过隐私协议,所以不需要再弹出隐私协议,也能调用已声明过的隐私接口 |
| | | // wx.getUserProfile() |
| | | } |
| | | }, |
| | | fail: (e) => { |
| | | console.log(e); |
| | | }, |
| | | }); |
| | | } |
| | | // 打开隐私政策 |
| | | function openPrivacyContract() { |
| | | wx.openPrivacyContract({ |
| | | success: () => {}, // 打开成功 |
| | | fail: (e) => { |
| | | uni.$u.toast(`打开失败:${e}`); |
| | | }, // 打开失败 |
| | | }); |
| | | } |
| | | |
| | | // 同意 |
| | | function agree(e) { |
| | | const buttonId = e.target.id || "agree-btn"; |
| | | emit("agree", buttonId); |
| | | emit("update:modelValue", false); |
| | | } |
| | | |
| | | // 拒绝 |
| | | function disagree() { |
| | | emit("disagree"); |
| | | closeAgreePrivacy(); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // 检测是否授权 |
| | | checkPrivacySetting(); |
| | | |
| | | // // 监听授权 |
| | | // wx.onNeedPrivacyAuthorization((resolve, eventInfo) => { |
| | | // emit('update:modelValue', true); |
| | | // // 回调 |
| | | // emit('needPrivacyAuthorization', resolve, eventInfo); |
| | | // }); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .button { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | //height: 80rpx; |
| | | padding: 10px 20px; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | line-height: 1.5; |
| | | color: #fff; |
| | | text-align: center; |
| | | text-decoration: none; |
| | | border-radius: 18rpx; |
| | | //border-width: 1px; |
| | | //border-style: solid; |
| | | } |
| | | |
| | | .button-lg { |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | justify-content: center; |
| | | //height: 80rpx; |
| | | padding: 12px 22px; |
| | | font-size: 14px; |
| | | font-weight: 700; |
| | | line-height: 1.5; |
| | | color: #fff; |
| | | text-align: center; |
| | | text-decoration: none; |
| | | border-radius: 20rpx; |
| | | //border-width: 1px; |
| | | //border-style: solid; |
| | | } |
| | | |
| | | .button-default { |
| | | color: #07c160; |
| | | background-color: rgb(0 0 0 / 5%); |
| | | } |
| | | |
| | | .button-primary { |
| | | color: #fff; |
| | | background-color: #07c160; |
| | | } |
| | | |
| | | button { |
| | | padding: 0; |
| | | margin: 0; |
| | | line-height: inherit; |
| | | background-color: transparent; |
| | | border-radius: 0; |
| | | outline: none; |
| | | } |
| | | |
| | | button::after { |
| | | border: none; |
| | | } |
| | | |
| | | .text-decoration { |
| | | color: #07c160; |
| | | text-decoration: underline; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view> |
| | | <picker |
| | | range-key="label" |
| | | :range="langOptions" |
| | | :value="langIndex" |
| | | @change="handleLangChange" |
| | | > |
| | | <slot> |
| | | <view class="i-mdi-language" :style="langStyle" /> |
| | | </slot> |
| | | </picker> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useI18n } from "vue-i18n"; |
| | | |
| | | const props = defineProps({ |
| | | size: { |
| | | type: Number, |
| | | default: 40, |
| | | required: false, |
| | | }, |
| | | }); |
| | | const emit = defineEmits(["change"]); |
| | | const { locale, t } = useI18n(); |
| | | const langStyle = { |
| | | fontSize: `${props.size}rpx`, |
| | | }; |
| | | const langOptions = computed(() => { |
| | | return [ |
| | | { label: t("locale.en"), value: "en" }, |
| | | { label: t("locale.zh-hans"), value: "zh-Hans" }, |
| | | ]; |
| | | }); |
| | | const langIndex = computed(() => { |
| | | return langOptions.value.findIndex((item) => { |
| | | return item.value === locale.value; |
| | | }); |
| | | }); |
| | | |
| | | function handleLangChange(event) { |
| | | const lang = langOptions.value[event.detail.value].value; |
| | | locale.value = lang; |
| | | uni.setLocale(lang); |
| | | emit("change", lang); |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| New file |
| | |
| | | <template> |
| | | <view class="flex flex-wrap gap-3"> |
| | | <view |
| | | v-for="(item, index) in colors" |
| | | :key="index" |
| | | class="mb-10rpx h-40rpx w-40rpx center cursor-pointer border-4rpx border-gray-300 rounded-4rpx border-solid" |
| | | :class="{ 'border-white': theme === item.name }" |
| | | :style="{ backgroundColor: item.color }" |
| | | @click="changeTheme(item.name)" |
| | | > |
| | | <view v-if="theme === item.name" class="i-mdi-check text-32rpx c-#fff" /> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { useAppStore } from "@/store"; |
| | | |
| | | const appStore = useAppStore(); |
| | | |
| | | const colors = [ |
| | | { |
| | | name: "", |
| | | color: "#21d59d", |
| | | }, |
| | | { |
| | | name: "blue", |
| | | color: "#3c9cff", |
| | | }, |
| | | ]; |
| | | |
| | | const theme = computed(() => appStore.getTheme); |
| | | |
| | | function changeTheme(theme) { |
| | | appStore.setTheme(theme); |
| | | } |
| | | </script> |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-12-15 17:51:08 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-16 15:01:04 |
| | | * @FilePath : \src\config\env.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-12-15 17:51:08 |
| | | */ |
| | | // 如果是打包app,需要改这里,h5不需要改这里 |
| | | const development = { |
| | | VITE_APP_ENV:'development', |
| | | // 开发环境这里改为自己的 |
| | | VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper', |
| | | // VITE_APP_WEBVIEW_URL: 'http://localhost:5173/drone-app-web-view/#/webViewWrapper', |
| | | VITE_API_BASE_URL: 'https://wrj.shuixiongit.com/api', |
| | | // VITE_API_BASE_URL: 'https://aisky.org.cn/api', |
| | | VITE_APP_WS_API_URL:'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws', |
| | | |
| | | // 静态资源存放地址' |
| | | VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets' |
| | | } |
| | | |
| | | const test = { |
| | | VITE_APP_ENV: 'test', |
| | | VITE_APP_WEBVIEW_URL: 'https://wrj.shuixiongit.com/drone-app-web-view/#/webViewWrapper', |
| | | VITE_API_BASE_URL: 'https://wrj.shuixiongit.com/api', |
| | | VITE_APP_WS_API_URL: 'wss://wrj.shuixiongit.com/drone-wss/api/v1/ws', |
| | | // 静态资源存放地址' |
| | | VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets' |
| | | } |
| | | |
| | | const production = { |
| | | VITE_APP_ENV: 'production', |
| | | VITE_APP_WEBVIEW_URL: 'https://aisky.org.cn/drone-app-web-view/#/webViewWrapper', |
| | | VITE_API_BASE_URL: 'https://aisky.org.cn/api', |
| | | VITE_APP_WS_API_URL: 'wss://aisky.org.cn/drone-wss/api/v1/ws', |
| | | // 静态资源存放地址' |
| | | VITE_APP_ASSETS_URL: 'https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets' |
| | | } |
| | | |
| | | export default { |
| | | development, |
| | | test, |
| | | production |
| | | } |
| New file |
| | |
| | | /** |
| | | * 全局配置文件 |
| | | */ |
| | | export default { |
| | | title: '', |
| | | logo: 'S', |
| | | key: 'saber', //配置主键,目前用于存储 |
| | | indexTitle: 'BladeX 微服务平台', |
| | | clientId: 'drone', // 客户端id |
| | | clientSecret: 'drone_secret', // 客户端密钥 |
| | | tenantMode: false, // 是否开启租户模式 |
| | | tenantId: '000000', // 管理组租户编号 |
| | | captchaMode: false, // 是否开启验证码模式 |
| | | switchMode: false, // 是否开启登录切换角色部门 |
| | | lockPage: '/lock', |
| | | tokenTime: 3000, |
| | | tokenHeader: 'Blade-Auth', |
| | | //HTTP状态码白名单 |
| | | statusWhiteList: [], |
| | | //配置首页不可关闭 |
| | | setting: { |
| | | sidebar: 'vertical', |
| | | tag: true, |
| | | debug: true, |
| | | collapse: true, |
| | | search: true, |
| | | color: true, |
| | | lock: true, |
| | | screenshot: true, |
| | | fullscreen: true, |
| | | theme: true, |
| | | menu: true, |
| | | }, |
| | | //首页配置 |
| | | fistPage: { |
| | | // name: '首页', |
| | | // path: '/wel/index', |
| | | name: '门户页', |
| | | path: '/wel/gatewayPage', |
| | | }, |
| | | //配置菜单的属性 |
| | | menu: { |
| | | iconDefault: 'icon-caidan', |
| | | label: 'name', |
| | | path: 'path', |
| | | icon: 'source', |
| | | children: 'children', |
| | | query: 'query', |
| | | href: 'path', |
| | | meta: 'meta', |
| | | }, |
| | | //水印配置 |
| | | watermark: { |
| | | mode: false, |
| | | text: 'BladeX', |
| | | }, |
| | | //oauth2配置 |
| | | oauth2: { |
| | | // 是否开启注册功能 |
| | | registerMode: true, |
| | | // 使用后端工程 @org.springblade.test.Sm2KeyGenerator 获取 |
| | | publicKey: '请配置国密sm2公钥', |
| | | // 第三方系统授权地址 |
| | | authUrl: 'http://localhost/blade-auth/oauth/render', |
| | | // 单点登录系统认证 |
| | | ssoMode: false, // 是否开启单点登录功能 |
| | | ssoBaseUrl: 'http://localhost:8100', // 单点登录系统地址(cloud端口为8100,boot端口为80) |
| | | ssoAuthUrl: '/oauth/authorize?client_id=saber3&response_type=code&redirect_uri=', // 单点登录授权地址 |
| | | ssoLogoutUrl: '/oauth/authorize/logout?redirect_uri=', // 单点登录退出地址 |
| | | redirectUri: 'http://localhost:2888/login', // 单点登录回调地址(Saber服务的登录界面地址) |
| | | }, |
| | | //设计器配置 |
| | | design: { |
| | | // 流程设计器类型(true->nutflow,false->flowable) |
| | | designMode: true, |
| | | // 流程设计器地址(flowable模式) |
| | | designUrl: 'http://localhost:9999', |
| | | // 报表设计器地址(cloud端口为8108,boot端口为80) |
| | | reportUrl: 'http://localhost:8108/ureport', |
| | | // 规则设计引擎地址 |
| | | edgeUrl: 'http://localhost:1880', |
| | | }, |
| | | } |
| New file |
| | |
| | | import useClipboard from "./use-clipboard" |
| | | import useLoading from "./use-loading" |
| | | import useLocation from "./use-location" |
| | | import useModal from "./use-modal" |
| | | import usePermission from "./use-permission" |
| | | import useShare from "./use-share" |
| | | import useTheme from "./use-theme" |
| | | import useTabAddButton from "./useTabAddButton" |
| | | |
| | | export { |
| | | useClipboard, |
| | | useLoading, |
| | | useLocation, |
| | | useModal, |
| | | usePermission, |
| | | useShare, |
| | | useTheme, |
| | | useTabAddButton |
| | | } |
| New file |
| | |
| | | /** |
| | | * 剪切板 |
| | | * @example |
| | | * const {setClipboardData, getClipboardData} = useClipboard() |
| | | * // 设置剪切板 |
| | | * setClipboardData({data: '1234567890'}) |
| | | * // 获取剪切板 |
| | | * const data = await getClipboardData() |
| | | */ |
| | | export default function useClipboard () { |
| | | const setClipboardData = ({ data, showToast = true }) => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.setClipboardData({ |
| | | data, |
| | | showToast, |
| | | success: ({ data }) => resolve(data), |
| | | fail: error => reject(error) |
| | | }) |
| | | }) |
| | | } |
| | | const getClipboardData = () => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.getClipboardData({ |
| | | success: ({ data }) => resolve(data), |
| | | fail: error => reject(error) |
| | | }) |
| | | }) |
| | | } |
| | | return { |
| | | setClipboardData, |
| | | getClipboardData |
| | | } |
| | | } |
| New file |
| | |
| | | /** |
| | | * loading 提示框 |
| | | * @example |
| | | * const {showLoading, hideLoading} = useLoading() |
| | | * // 显示loading |
| | | * showLoading() |
| | | * // 隐藏loading |
| | | * hideLoading() |
| | | */ |
| | | export default function useLoading () { |
| | | const showLoading = (content = "加载中") => { |
| | | uni.showLoading({ |
| | | title: content, |
| | | mask: true |
| | | }) |
| | | } |
| | | const hideLoading = () => { |
| | | uni.hideLoading() |
| | | } |
| | | return { |
| | | showLoading, |
| | | hideLoading |
| | | } |
| | | } |
| New file |
| | |
| | | /** |
| | | * 定位hooks,提供定位相关功能 |
| | | * - 获取位置 |
| | | * - 位置监听 |
| | | * - 地址解析 |
| | | * - 距离计算 |
| | | */ |
| | | export default function useLocation () { |
| | | // 当前位置信息 |
| | | const location = ref(null) |
| | | |
| | | // 定位状态 |
| | | const isLocating = ref(false) |
| | | |
| | | // 是否正在监听位置 |
| | | const isWatching = ref(false) |
| | | |
| | | // 定位错误信息 |
| | | const error = ref(null) |
| | | |
| | | // 历史位置 |
| | | const historyLocations = ref([]) |
| | | |
| | | // 监听位置的定时器ID |
| | | let watchId = null |
| | | |
| | | /** |
| | | * 获取当前位置 |
| | | * @param options 定位选项 |
| | | */ |
| | | const getLocation = (options = {}) => { |
| | | isLocating.value = true |
| | | error.value = null |
| | | |
| | | const defaultOptions = { |
| | | type: "gcj02", |
| | | altitude: false, |
| | | isHighAccuracy: false |
| | | } |
| | | |
| | | const finalOptions = { ...defaultOptions, ...options } |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | uni.getLocation({ |
| | | type: finalOptions.type, |
| | | altitude: finalOptions.altitude, |
| | | isHighAccuracy: finalOptions.isHighAccuracy, |
| | | highAccuracyExpireTime: finalOptions.highAccuracyExpireTime, |
| | | success: res => { |
| | | // 更新当前位置 |
| | | const locationData = { |
| | | ...res, |
| | | timestamp: Date.now() |
| | | } |
| | | |
| | | location.value = locationData |
| | | |
| | | // 添加到历史记录 |
| | | historyLocations.value.push(locationData) |
| | | |
| | | // 只保留最近的20条记录 |
| | | if (historyLocations.value.length > 20) { |
| | | historyLocations.value.shift() |
| | | } |
| | | |
| | | finalOptions.success && finalOptions.success(res) |
| | | resolve(locationData) |
| | | }, |
| | | fail: err => { |
| | | error.value = err |
| | | finalOptions.fail && finalOptions.fail(err) |
| | | reject(err) |
| | | }, |
| | | complete: () => { |
| | | isLocating.value = false |
| | | finalOptions.complete && finalOptions.complete() |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 使用地理编码获取地址信息 |
| | | * @param latitude 纬度 |
| | | * @param longitude 经度 |
| | | */ |
| | | const getAddress = (latitude, longitude) => { |
| | | return new Promise((resolve, reject) => { |
| | | // #ifdef APP-PLUS |
| | | uni.request({ |
| | | url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=YOUR_KEY`, |
| | | success: res => { |
| | | if (res.data && res.data.status === 0) { |
| | | const addressComponent = res.data.result.address_component |
| | | const formattedAddress = |
| | | res.data.result.formatted_addresses.recommend |
| | | |
| | | const addressInfo = { |
| | | nation: addressComponent.nation, |
| | | province: addressComponent.province, |
| | | city: addressComponent.city, |
| | | district: addressComponent.district, |
| | | street: addressComponent.street, |
| | | streetNum: addressComponent.street_number, |
| | | poiName: |
| | | res.data.result.poi_count > 0 |
| | | ? res.data.result.pois[0].title |
| | | : "", |
| | | cityCode: res.data.result.ad_info.city_code |
| | | } |
| | | |
| | | if (location.value) { |
| | | location.value.address = addressInfo |
| | | location.value.formatted = formattedAddress |
| | | } |
| | | |
| | | resolve(addressInfo) |
| | | } else { |
| | | reject(new Error("获取地址信息失败")) |
| | | } |
| | | }, |
| | | fail: err => { |
| | | reject(err) |
| | | } |
| | | }) |
| | | // #endif |
| | | |
| | | // #ifndef APP-PLUS |
| | | // 其他平台可以使用uni.getLocation的geocode参数获取(仅App和微信小程序支持) |
| | | // 或者使用其他地图服务的API |
| | | reject(new Error("当前平台不支持地址解析")) |
| | | // #endif |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 停止监听位置 |
| | | */ |
| | | const stopWatchLocation = () => { |
| | | if (watchId !== null) { |
| | | clearInterval(watchId) |
| | | watchId = null |
| | | } |
| | | |
| | | isWatching.value = false |
| | | } |
| | | |
| | | /** |
| | | * 开始监听位置变化 |
| | | * @param options 定位选项 |
| | | * @param interval 监听间隔,单位毫秒 |
| | | */ |
| | | const watchLocation = (options = {}, interval = 5000) => { |
| | | // 已经在监听,先停止 |
| | | if (isWatching.value) { |
| | | stopWatchLocation() |
| | | } |
| | | |
| | | isWatching.value = true |
| | | |
| | | // 首次定位 |
| | | getLocation(options).catch(err => { |
| | | console.error("监听位置首次定位失败", err) |
| | | }) |
| | | |
| | | // 定时获取位置 |
| | | watchId = window.setInterval(() => { |
| | | if (isWatching.value) { |
| | | getLocation(options).catch(err => { |
| | | console.error("监听位置更新失败", err) |
| | | }) |
| | | } |
| | | }, interval) |
| | | |
| | | return watchId |
| | | } |
| | | |
| | | /** |
| | | * 计算两点间距离(米) |
| | | * @param lat1 第一个点的纬度 |
| | | * @param lon1 第一个点的经度 |
| | | * @param lat2 第二个点的纬度 |
| | | * @param lon2 第二个点的经度 |
| | | * @returns 距离,单位:米 |
| | | */ |
| | | const calculateDistance = (lat1, lon1, lat2, lon2) => { |
| | | const R = 6371000 // 地球半径,单位米 |
| | | const dLat = ((lat2 - lat1) * Math.PI) / 180 |
| | | const dLon = ((lon2 - lon1) * Math.PI) / 180 |
| | | |
| | | const a = |
| | | Math.sin(dLat / 2) * Math.sin(dLat / 2) + |
| | | Math.cos((lat1 * Math.PI) / 180) * |
| | | Math.cos((lat2 * Math.PI) / 180) * |
| | | Math.sin(dLon / 2) * |
| | | Math.sin(dLon / 2) |
| | | |
| | | const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)) |
| | | const distance = R * c |
| | | |
| | | return distance |
| | | } |
| | | |
| | | /** |
| | | * 获取当前位置到目标位置的距离 |
| | | * @param targetLat 目标位置纬度 |
| | | * @param targetLon 目标位置经度 |
| | | * @returns 距离,单位:米,如果当前没有位置信息则返回-1 |
| | | */ |
| | | const getDistanceFromCurrent = (targetLat, targetLon) => { |
| | | if (!location.value) { |
| | | return -1 |
| | | } |
| | | |
| | | return calculateDistance( |
| | | location.value.latitude, |
| | | location.value.longitude, |
| | | targetLat, |
| | | targetLon |
| | | ) |
| | | } |
| | | |
| | | /** |
| | | * 格式化距离显示 |
| | | * @param distance 距离,单位:米 |
| | | * @returns 格式化后的距离字符串 |
| | | */ |
| | | const formatDistance = distance => { |
| | | if (distance < 0) { |
| | | return "未知距离" |
| | | } else if (distance < 1000) { |
| | | return `${Math.round(distance)}米` |
| | | } else { |
| | | return `${(distance / 1000).toFixed(1)}公里` |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 打开导航 |
| | | * @param latitude 目标纬度 |
| | | * @param longitude 目标经度 |
| | | * @param name 目标名称 |
| | | * @param address 目标地址 |
| | | */ |
| | | const openLocation = (latitude, longitude, name = "", address = "") => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.openLocation({ |
| | | latitude, |
| | | longitude, |
| | | name, |
| | | address, |
| | | success: () => resolve(), |
| | | fail: err => reject(err) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 选择位置 |
| | | */ |
| | | const chooseLocation = () => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.chooseLocation({ |
| | | success: res => { |
| | | // 更新当前位置 |
| | | if (res.latitude && res.longitude) { |
| | | const locationData = { |
| | | latitude: res.latitude, |
| | | longitude: res.longitude, |
| | | accuracy: 0, |
| | | verticalAccuracy: 0, |
| | | horizontalAccuracy: 0, |
| | | altitude: 0, |
| | | speed: 0, |
| | | timestamp: Date.now(), |
| | | address: { |
| | | province: "", |
| | | city: "", |
| | | district: "", |
| | | street: "", |
| | | poiName: res.name |
| | | }, |
| | | formatted: res.address |
| | | } |
| | | |
| | | location.value = locationData |
| | | } |
| | | |
| | | resolve(res) |
| | | }, |
| | | fail: err => reject(err) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 自动清理 |
| | | onUnmounted(() => { |
| | | stopWatchLocation() |
| | | }) |
| | | |
| | | return { |
| | | // 状态 |
| | | location, |
| | | isLocating, |
| | | isWatching, |
| | | error, |
| | | historyLocations, |
| | | |
| | | // 方法 |
| | | getLocation, |
| | | getAddress, |
| | | watchLocation, |
| | | stopWatchLocation, |
| | | calculateDistance, |
| | | getDistanceFromCurrent, |
| | | formatDistance, |
| | | openLocation, |
| | | chooseLocation |
| | | } |
| | | } |
| New file |
| | |
| | | /** |
| | | * Dialog 提示框 |
| | | * @example |
| | | * const {showModal} = useModal() |
| | | * showModal('提示内容') |
| | | */ |
| | | export default function useModal () { |
| | | const showModal = (content, options) => { |
| | | return new Promise((resolve, reject) => { |
| | | uni.showModal({ |
| | | title: "温馨提示", |
| | | content, |
| | | showCancel: false, |
| | | confirmColor: "#1677FF", |
| | | success: res => resolve(res), |
| | | fail: () => reject(new Error("Alert 调用失败 !")), |
| | | ...options |
| | | }) |
| | | }) |
| | | } |
| | | return { |
| | | showModal |
| | | } |
| | | } |
| New file |
| | |
| | | import { hasPerm } from "@/plugins/permission" |
| | | import { currentRoute } from "@/router" |
| | | |
| | | // 对某些特殊场景需要在页面onShow生命周期中校验权限: |
| | | // 1.微信小程序端点击tabbar的底层逻辑不触发uni.switchTab |
| | | // 2.h5在浏览器地址栏输入url后跳转不触发uni的路由api |
| | | // 3.首次启动加载的页面不触发uni的路由api |
| | | export default async function usePermission () { |
| | | return hasPerm(currentRoute()) |
| | | } |
| New file |
| | |
| | | /** |
| | | * 小程序分享 |
| | | * @param {object} options |
| | | * @example |
| | | * // 必须要调用onShareAppMessage,onShareTimeline才能正常分享 |
| | | * // 因为小程序平台,必须在注册页面时,主动配置onShareAppMessage, onShareTimeline才可以 |
| | | * // 组合式API是运行时才能注册,框架不可能默认给每个页面都开启这两个分享,所以必须在页面代码里包含这两个API的字符串,才会主动去注册。 |
| | | * // 相关说明链接:https://ask.dcloud.net.cn/question/150353 |
| | | * const {onShareAppMessage, onShareTimeline} = useShare({title: '分享标题', path: 'pages/index/index', query: 'id=1', imageUrl: 'https://xxx.png'}) |
| | | * onShareAppMessage() |
| | | * onShareTimeline() |
| | | */ |
| | | export default function useShare (options) { |
| | | // #ifdef MP-WEIXIN |
| | | const title = options?.title ?? "" |
| | | const path = options?.path ?? "" |
| | | const query = options?.query ?? "" |
| | | const imageUrl = options?.imageUrl ?? "" |
| | | |
| | | const shareApp = (params = {}) => { |
| | | onShareAppMessage(() => { |
| | | return { |
| | | title, |
| | | path: path ? `${path}${query ? `?${query}` : ""}` : "", |
| | | imageUrl, |
| | | ...params |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const shareTime = (params = {}) => { |
| | | onShareTimeline(() => { |
| | | return { |
| | | title, |
| | | query: options?.query ?? "", |
| | | imageUrl, |
| | | ...params |
| | | } |
| | | }) |
| | | } |
| | | return { |
| | | onShareAppMessage: shareApp, |
| | | onShareTimeline: shareTime |
| | | } |
| | | // #endif |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:48:36 |
| | | * @FilePath : \src\hooks\use-theme\index.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import { computed } from "vue" |
| | | import { useAppStore } from "@/store" |
| | | |
| | | /** |
| | | * 主题Hook |
| | | */ |
| | | export default function useTheme () { |
| | | const appStore = useAppStore() |
| | | |
| | | // 当前主题模式 |
| | | const theme = computed(() => appStore.getTheme) |
| | | |
| | | // 是否为深色主题 |
| | | const isDark = computed(() => appStore.getTheme === "dark") |
| | | |
| | | /** |
| | | * 设置主题 |
| | | */ |
| | | const setTheme = mode => { |
| | | appStore.setTheme(mode) |
| | | } |
| | | |
| | | /** |
| | | * 切换主题 |
| | | */ |
| | | const toggleTheme = () => { |
| | | const newTheme = theme.value === "light" ? "dark" : "light" |
| | | appStore.setTheme(newTheme) |
| | | } |
| | | |
| | | return { |
| | | theme, |
| | | isDark, |
| | | setTheme, |
| | | toggleTheme |
| | | } |
| | | } |
| New file |
| | |
| | | import {useUserStore} from "@/store/index.js"; |
| | | import {getEnvObj} from "@/utils/index.js"; |
| | | import {enterRoom} from "@/utils/voiceCallByTX/index.js"; |
| | | import useAppStore from "../store/modules/app/index.js"; |
| | | |
| | | let socketTask = null |
| | | |
| | | export function useGlobalWS() { |
| | | const userStore = useUserStore(); |
| | | const appStore = useAppStore(); |
| | | |
| | | const userId = computed(() => userStore?.userInfo?.user_id) |
| | | const access_token = computed(() => userStore?.userInfo?.access_token) |
| | | const {VITE_APP_WS_API_URL} = getEnvObj() |
| | | |
| | | // 消息处理 |
| | | function messageHandler(payload) { |
| | | switch (payload.biz_code) { |
| | | case 'JOB_ISREFRESH': |
| | | appStore.setJobUpdateKeyAdd() |
| | | break |
| | | case 'DEVICE_ISREFRESH': |
| | | appStore.setDeviceUpdateKeyAdd() |
| | | break |
| | | case 'DOWNLOAD_PROGRESS': |
| | | break |
| | | case 'LOGOUT_USER': |
| | | userStore.setUserInfo(null) |
| | | uni.reLaunch({ |
| | | url: '/pages/login/index' |
| | | }) |
| | | break |
| | | case 'VoiceCall': |
| | | enterRoom(payload, userId.value) |
| | | break |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | // 关闭ws |
| | | function closeWS() { |
| | | socketTask?.close({ |
| | | success: () => { |
| | | console.log('ws关闭连接'); |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | // 初始化ws |
| | | function initWS() { |
| | | // 关闭,再连接ws |
| | | closeWS() |
| | | if (!access_token.value) return |
| | | const url = VITE_APP_WS_API_URL |
| | | + `?x-auth-token=${encodeURI(access_token?.value)}` |
| | | + `&model_type=3&workspace-id=${userId.value}` |
| | | // 创建连接 |
| | | socketTask = uni.connectSocket({ |
| | | url: url, |
| | | success: () => { |
| | | console.log('ws连接成功'); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('ws连接失败:', err); |
| | | } |
| | | }); |
| | | // 消息监听 |
| | | socketTask.onMessage((result) => { |
| | | messageHandler(JSON.parse(result.data)) |
| | | }) |
| | | //================================== |
| | | // 监听连接打开 |
| | | socketTask.onOpen((res) => { |
| | | console.log('✅ WebSocket连接已建立') |
| | | // reconnectAttempts = 0 // 连接成功后重置重连次数 |
| | | // 可以在这里发送心跳或订阅消息 |
| | | // startHeartbeat() |
| | | }) |
| | | // 监听连接关闭 |
| | | socketTask.onClose((res) => { |
| | | console.log(`WebSocket连接关闭,代码: ${res.code}, 原因: ${res.reason}`) |
| | | |
| | | // 根据不同的关闭代码处理 |
| | | if (res.code === 1000) { // 正常关闭 |
| | | console.log('连接正常关闭') |
| | | } else if (res.code === 1006) { // 异常关闭 |
| | | console.log('连接异常关闭,尝试重连...') |
| | | } else if (res.code === 1011) { // 服务器内部错误 |
| | | console.log('服务器内部错误(1011),延迟重连...') |
| | | } else { |
| | | console.log('其他原因关闭,尝试重连...') |
| | | } |
| | | }) |
| | | |
| | | // 监听错误 |
| | | socketTask.onError((err) => { |
| | | console.error('WebSocket发生错误:', err) |
| | | }) |
| | | } |
| | | |
| | | |
| | | watch(access_token, initWS, {immediate: true}) |
| | | } |
| New file |
| | |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | |
| | | export default function useTabAddButton (visible) { |
| | | onShow(()=>{ |
| | | // const tabList = uni.getTabBar().list; |
| | | // uni.setTabBarItem({ |
| | | // index: 2, // Tab 的索引(从0开始) |
| | | // visible, |
| | | // }); |
| | | }) |
| | | } |
| New file |
| | |
| | | import { createI18n } from "vue-i18n" |
| | | import en from "./langs/en" |
| | | import zhHans from "./langs/zh-Hans" |
| | | |
| | | const i18n = createI18n({ |
| | | legacy: false, // 必须设置false才能使用Composition API |
| | | globalInjection: true, // 为每个组件注入$为前缀的全局属性和函数 |
| | | locale: uni.getLocale(), |
| | | messages: { |
| | | en, |
| | | "zh-Hans": zhHans |
| | | } |
| | | }) |
| | | |
| | | function setupI18n (app) { |
| | | app.use(i18n) |
| | | } |
| | | |
| | | export { i18n } |
| | | export default setupI18n |
| New file |
| | |
| | | export default { |
| | | locale: { |
| | | auto: "System", |
| | | en: "English", |
| | | "zh-hans": "Chinese" |
| | | }, |
| | | home: { |
| | | intro: "Welcome to uni-app demo", |
| | | "toggle-langs": "Change languages" |
| | | } |
| | | } |
| New file |
| | |
| | | export default { |
| | | locale: { |
| | | auto: "系统", |
| | | en: "英语", |
| | | "zh-hans": "中文" |
| | | }, |
| | | home: { |
| | | intro: "欢迎来到uni-app演示", |
| | | "toggle-langs": "切换语言" |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:39:15 |
| | | * @FilePath : \src\main.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import { createSSRApp } from "vue" |
| | | import App from "@/App.vue" |
| | | import setupPlugins from "@/plugins" |
| | | // 引入UnoCSS |
| | | import "virtual:uno.css" |
| | | import 'leaflet/dist/leaflet.css' |
| | | import './static/fonts/font.css' |
| | | import {getEnvObj} from "@/utils/index.js"; |
| | | console.log('当前环境变量',getEnvObj()) |
| | | export function createApp () { |
| | | const app = createSSRApp(App) |
| | | app.use(setupPlugins) |
| | | |
| | | return { |
| | | app |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "name" : "掌控智飞", |
| | | "appid" : "__UNI__0981D7F", |
| | | "description" : "", |
| | | "versionName" : "1.0.0", |
| | | "versionCode" : "100", |
| | | "transformPx" : false, |
| | | /* 5+App特有相关 */ |
| | | "app-plus" : { |
| | | "orientation" : [ |
| | | //竖屏正方向 |
| | | "portrait-primary", |
| | | //竖屏反方向 |
| | | "portrait-secondary", |
| | | //横屏正方向 |
| | | "landscape-primary", |
| | | //横屏反方向 |
| | | "landscape-secondary", |
| | | //自然方向 |
| | | "default" |
| | | ], |
| | | "usingComponents" : true, |
| | | "nvueStyleCompiler" : "uni-app", |
| | | "compilerVersion" : 3, |
| | | "splashscreen" : { |
| | | "alwaysShowBeforeRender" : true, |
| | | "waiting" : true, |
| | | "autoclose" : true, |
| | | "delay" : 0 |
| | | }, |
| | | /* 模块配置 */ |
| | | "modules" : {}, |
| | | /* 应用发布信息 */ |
| | | "distribute" : { |
| | | /* android打包配置 */ |
| | | "android" : { |
| | | "permissions" : [ |
| | | "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", |
| | | "<uses-permission android:name=\"android.permission.VIBRATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.READ_LOGS\"/>", |
| | | "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", |
| | | "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", |
| | | "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.CAMERA\"/>", |
| | | "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", |
| | | "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", |
| | | "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", |
| | | "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", |
| | | "<uses-feature android:name=\"android.hardware.camera\"/>", |
| | | "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>", |
| | | "<uses-permission android:name=\"android.permission.RECORD_AUDIO\" />" |
| | | ] |
| | | }, |
| | | /* ios打包配置 */ |
| | | "ios" : { |
| | | "dSYMs" : false |
| | | }, |
| | | /* SDK配置 */ |
| | | "sdkConfigs" : {}, |
| | | "icons" : { |
| | | "android" : { |
| | | "hdpi" : "src/static/images/app-logo.png", |
| | | "xhdpi" : "src/static/images/app-logo.png", |
| | | "xxhdpi" : "src/static/images/app-logo.png", |
| | | "xxxhdpi" : "src/static/images/app-logo.png" |
| | | } |
| | | } |
| | | }, |
| | | "nativePlugins" : { |
| | | "TRTCCloudUniPlugin-TRTCCloudImpl" : { |
| | | "__plugin_info__" : { |
| | | "name" : "【官方】腾讯云实时音视频SDK", |
| | | "description" : "uni-app TRTC SDK 是腾讯云实时音视频通讯解决方案在 uni-app 上的 SDK,提供实时音视频服务", |
| | | "platforms" : "Android,iOS", |
| | | "url" : "https://ext.dcloud.net.cn/plugin?id=7774", |
| | | "android_package_name" : "uni.app.UNI0981D7F", |
| | | "ios_bundle_id" : "", |
| | | "isCloud" : true, |
| | | "bought" : 1, |
| | | "pid" : "7774", |
| | | "parameters" : {} |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | /* 快应用特有相关 */ |
| | | "quickapp" : {}, |
| | | /* 小程序特有相关 */ |
| | | "mp-weixin" : { |
| | | "appid" : "wx05742eafb412a57a", |
| | | "setting" : { |
| | | "urlCheck" : false |
| | | }, |
| | | "usingComponents" : true |
| | | }, |
| | | "mp-alipay" : { |
| | | "usingComponents" : true |
| | | }, |
| | | "mp-baidu" : { |
| | | "usingComponents" : true |
| | | }, |
| | | "mp-toutiao" : { |
| | | "usingComponents" : true |
| | | }, |
| | | "uniStatistics" : { |
| | | "enable" : false |
| | | }, |
| | | "vueVersion" : "3", |
| | | "h5" : { |
| | | "router" : { |
| | | "mode" : "hash", |
| | | "base" : "/work-wx/" |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | { |
| | | "easycom": { |
| | | "custom": { |
| | | "^u--(.*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^up-(.*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue", |
| | | "^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)": "z-paging/components/z-paging$1/z-paging$1.vue" |
| | | } |
| | | }, |
| | | "pages": [ |
| | | { |
| | | "path": "pages/work/index", |
| | | "style": { |
| | | "navigationBarTitleText": "事件工单", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/voiceCall/index", |
| | | "style": { |
| | | "navigationBarTitleText": "通话", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/map/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | |
| | | { |
| | | "path": "pages/user/index", |
| | | "style": { |
| | | "navigationBarTitleText": "我的", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/login/index", |
| | | "style": { |
| | | "navigationBarTitleText": "登录页", |
| | | "navigationStyle": "custom" |
| | | } |
| | | } |
| | | ], |
| | | "subPackages": [ |
| | | { |
| | | "root": "subPackages", |
| | | "pages": [ |
| | | { |
| | | "path": "404/index", |
| | | "style": { |
| | | "navigationBarTitleText": "404", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/index", |
| | | "style": { |
| | | "navigationBarTitleText": "工单详情" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/addWork/index", |
| | | "style": { |
| | | "navigationBarTitleText": "新建工单" |
| | | } |
| | | }, |
| | | { |
| | | "path": "workDetail/mapWork/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图展示", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "userDetail/infos/index", |
| | | "style": { |
| | | "navigationBarTitleText": "个人资料" |
| | | } |
| | | }, |
| | | { |
| | | "path": "userDetail/password/index", |
| | | "style": { |
| | | "navigationBarTitleText": "修改密码" |
| | | } |
| | | }, |
| | | { |
| | | "path": "browser/index", |
| | | "style": { |
| | | "navigationBarTitleText": "地图" |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ], |
| | | "tabBar": { |
| | | "color": "#8c8c8c", |
| | | "selectedColor": "#1D6FE9", |
| | | "borderStyle": "black", |
| | | "backgroundColor": "#ffffff", |
| | | "list": [ |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_order.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.png", |
| | | "pagePath": "pages/work/index", |
| | | "text": "工单" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_order.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_order_selected.png", |
| | | "pagePath": "pages/voiceCall/index", |
| | | "text": "通话" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_home1.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_home_selected.png", |
| | | "pagePath": "pages/map/index", |
| | | "text": "地图" |
| | | }, |
| | | { |
| | | "iconPath": "static/images/tabbar/icon_me.png", |
| | | "selectedIconPath": "static/images/tabbar/icon_me_selected.png", |
| | | "pagePath": "pages/user/index", |
| | | "text": "我的" |
| | | } |
| | | ] |
| | | }, |
| | | "globalStyle": { |
| | | "navigationBarTextStyle": "black", |
| | | "navigationBarTitleText": "uni-app", |
| | | "navigationBarBackgroundColor": "#F8F8F8", |
| | | "backgroundColor": "#F8F8F8" |
| | | } |
| | | } |
| New file |
| | |
| | | <!-- 登录页 --> |
| | | <template> |
| | | <view class="login-form-wrap"> |
| | | <image class="logo" :src="logoSvg" /> |
| | | <div class="title">掌控智飞</div> |
| | | <div class="user-name"> |
| | | <image :src="usernameSvg" /> |
| | | <input v-model="loginForm.username" placeholder="请输入用户名" /> |
| | | </div> |
| | | <div class="pass-word"> |
| | | <image :src="passwordSvg" /> |
| | | <input |
| | | v-model="loginForm.password" |
| | | type="password" |
| | | placeholder="请输入密码" |
| | | /> |
| | | </div> |
| | | <div class="remember-password"> |
| | | <label> |
| | | <checkbox-group @change="toggleRemember"> |
| | | <checkbox |
| | | :checked="rememberPassword" |
| | | color="#1D6FE9" |
| | | style="transform: scale(0.7)" |
| | | /> |
| | | </checkbox-group> |
| | | 记住密码 |
| | | </label> |
| | | </div> |
| | | |
| | | <button class="login-btn" :style="[inputStyle]" @tap="submit">登录</button> |
| | | <image class="lowerRightCorner" :src="droneSvg" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getAssetsImage } from "@/utils/index.js"; |
| | | import md5 from "js-md5"; |
| | | import { loginByUsername } from "@/api/user/index.js"; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | |
| | | import { HOME_PATH, LOGIN_PATH, removeQueryString } from "@/router"; |
| | | import { onMounted } from "vue"; |
| | | |
| | | const droneSvg = getAssetsImage("/images/login/droneSvg.svg"); |
| | | const usernameSvg = getAssetsImage("/images/login/username.svg"); |
| | | const passwordSvg = getAssetsImage("/images/login/password.svg"); |
| | | const logoSvg = getAssetsImage("/images/login/logo.svg"); |
| | | |
| | | const userStore = useUserStore(); |
| | | const loginForm = ref({ |
| | | username: "", |
| | | password: "", |
| | | }); |
| | | const rememberPassword = ref(false); |
| | | const inputStyle = computed(() => { |
| | | const style = {}; |
| | | if (loginForm.value.username && loginForm.value.password) { |
| | | style.color = "#fff"; |
| | | style.backgroundColor = "#1D6FE9"; |
| | | } |
| | | return style; |
| | | }); |
| | | let redirect = HOME_PATH; |
| | | function toggleRemember(e) { |
| | | rememberPassword.value = e.detail.value.length > 0; |
| | | } |
| | | |
| | | async function submit() { |
| | | if (!loginForm.value.username.trim()) { |
| | | uni.showToast({ |
| | | title: "请输入用户名", |
| | | icon: "none", |
| | | duration: 2000, |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (!loginForm.value.password.trim()) { |
| | | uni.showToast({ |
| | | title: "请输入密码", |
| | | icon: "none", |
| | | duration: 2000, |
| | | }); |
| | | return; |
| | | } |
| | | let userInfo = { |
| | | tenantId: "000000", |
| | | deptId: "", |
| | | roleId: "", |
| | | username: loginForm.value.username, |
| | | password: loginForm.value.password, |
| | | type: "account", |
| | | code: "", |
| | | key: "", |
| | | }; |
| | | |
| | | if (rememberPassword.value) { |
| | | uni.setStorageSync("rememberedUser", { |
| | | username: loginForm.value.username, |
| | | password: loginForm.value.password, |
| | | }); |
| | | } else { |
| | | uni.removeStorageSync("rememberedUser"); |
| | | } |
| | | |
| | | try { |
| | | const res = await loginByUsername( |
| | | userInfo.tenantId, |
| | | userInfo.deptId, |
| | | userInfo.roleId, |
| | | userInfo.username, |
| | | md5(userInfo.password), |
| | | userInfo.type, |
| | | userInfo.key, |
| | | userInfo.code |
| | | ); |
| | | userStore.setUserInfo(res.data); |
| | | uni.reLaunch({ |
| | | url: "/pages/map/index", |
| | | }); |
| | | } catch (error) { |
| | | const errorMsg = |
| | | error.data?.error_description !== "Bad credentials" |
| | | ? error.data?.error_description |
| | | : "登录失败,请重试"; |
| | | uni.showToast({ |
| | | title: errorMsg, |
| | | icon: "none", |
| | | duration: 2000, |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // 从本地存储加载记住的密码 |
| | | onMounted(() => { |
| | | const savedUserInfo = uni.getStorageSync("rememberedUser"); |
| | | console.log("记住密码", savedUserInfo); |
| | | if (savedUserInfo) { |
| | | loginForm.value.username = savedUserInfo.username; |
| | | loginForm.value.password = savedUserInfo.password; |
| | | rememberPassword.value = true; |
| | | } |
| | | }); |
| | | onLoad((options) => { |
| | | if (options.redirect && removeQueryString(options.redirect) !== LOGIN_PATH) { |
| | | redirect = decodeURIComponent(options.redirect); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .login-form-wrap { |
| | | position: relative; |
| | | text-align: center; |
| | | height: 100%; |
| | | width: 100%; |
| | | |
| | | .logo { |
| | | width: 127px; |
| | | height: 51px; |
| | | margin: 0 auto; |
| | | margin-top: 104px; |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .lowerRightCorner { |
| | | position: absolute; |
| | | right: 0; |
| | | bottom: 0; |
| | | width: 425.61rpx; |
| | | height: 316.46rpx; |
| | | } |
| | | |
| | | .title { |
| | | font-family: YouSheBiaoTiHei, YouSheBiaoTiHei; |
| | | font-weight: 400; |
| | | font-size: 84rpx; |
| | | line-height: 82rpx; |
| | | letter-spacing: 1px; |
| | | text-shadow: 0px 8px 8px rgba(0, 0, 0, 0.18); |
| | | text-align: center; |
| | | font-style: normal; |
| | | text-transform: none; |
| | | color: #1452d3; |
| | | text-align: center; |
| | | margin-bottom: 168rpx; |
| | | } |
| | | |
| | | .user-name, |
| | | .pass-word { |
| | | display: flex; |
| | | //justify-content: center; |
| | | align-items: center; |
| | | margin-left: 62rpx; |
| | | margin-right: 58rpx; |
| | | height: 118rpx; |
| | | border-bottom: 2rpx solid #e3e3e3; |
| | | |
| | | image { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | margin-right: 12rpx; |
| | | } |
| | | |
| | | :deep(uni-input) { |
| | | height: 40rpx; |
| | | line-height: 40rpx; |
| | | width: 80%; |
| | | margin-top: 20rpx; |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | :deep(input) { |
| | | height: 40rpx; |
| | | line-height: 40rpx; |
| | | width: 80%; |
| | | margin-top: 20rpx; |
| | | padding: 0 !important; |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | :deep(.uni-input-placeholder) { |
| | | font-size: 32rpx; |
| | | color: #e3e3e3; |
| | | font-weight: 500; |
| | | } |
| | | } |
| | | |
| | | .remember-password { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | margin-left: 62rpx; |
| | | margin-right: 58rpx; |
| | | margin-top: 20rpx; |
| | | |
| | | color: #666; |
| | | font-size: 28rpx; |
| | | |
| | | label { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | } |
| | | |
| | | input { |
| | | @apply pb-6rpx mb-10rpx text-left; |
| | | } |
| | | |
| | | .tips { |
| | | @apply mt-8rpx mb-60rpx; |
| | | color: $u-info; |
| | | } |
| | | |
| | | .login-btn { |
| | | z-index: 1; |
| | | @apply flex items-center justify-center py-12rpx px-0 text-30rpx border-none; |
| | | background: #1d6fe9; |
| | | color: white; |
| | | width: 590rpx; |
| | | height: 76rpx; |
| | | border-radius: 40rpx 40rpx 40rpx 40rpx; |
| | | margin-top: 100rpx; |
| | | |
| | | &::after { |
| | | @apply border-none; |
| | | } |
| | | } |
| | | |
| | | .alternative { |
| | | @apply flex justify-between mt-30rpx; |
| | | color: $u-tips-color; |
| | | } |
| | | } |
| | | |
| | | .login-type-wrap { |
| | | @apply flex justify-between pt-350rpx px-150rpx pb-150rpx; |
| | | |
| | | .item { |
| | | @apply flex items-center flex-col text-28rpx; |
| | | color: $u-content-color; |
| | | } |
| | | } |
| | | |
| | | .hint { |
| | | @apply px-40rpx py-20rpx text-24rpx; |
| | | color: $u-tips-color; |
| | | |
| | | .link { |
| | | color: $u-warning; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="panel-container" :style="{ |
| | | transform: `translateY(${translateY}px)`, |
| | | transition: isDragging ? 'none' : 'transform 0.3s ease', |
| | | }" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd"> |
| | | <!-- 顶部拖拽提示条 --> |
| | | <view class="drag-bar"></view> |
| | | |
| | | <!-- 搜索框(带毛玻璃) --> |
| | | <view class="search-box" :style="searchBoxStyle"> |
| | | <slot name="searchBox"></slot> |
| | | </view> |
| | | |
| | | <!-- 内容区 --> |
| | | <scroll-view scroll-y class="panel-content"> |
| | | <view class="dummy-content"> |
| | | <text>这里可以放搜索结果、推荐地点等内容</text> |
| | | </view> |
| | | </scroll-view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | ref, |
| | | computed, |
| | | onMounted, |
| | | watch |
| | | } from 'vue' |
| | | |
| | | const props = defineProps({ |
| | | isSelectInput: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | searchVal: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | }) |
| | | |
| | | // 获取屏幕高度 |
| | | let screenHeight = 0 |
| | | |
| | | // 拖拽状态 |
| | | const startY = ref(0) |
| | | const currentY = ref(0) |
| | | const translateY = ref(0) |
| | | const isDragging = ref(false) |
| | | |
| | | const initialPosition = ref(0.8) |
| | | const oneSlidePosition = ref(0.6) |
| | | const twoSlidePosition = ref(0.1) |
| | | |
| | | // 毛玻璃效果 |
| | | const searchBoxStyle = computed(() => { |
| | | return translateY.value <= screenHeight * oneSlidePosition.value ? |
| | | { |
| | | backdropFilter: 'blur(10px)', |
| | | background: 'rgba(255, 255, 255, 0.7)', |
| | | } : |
| | | { |
| | | background: '#fff', |
| | | } |
| | | }) |
| | | |
| | | watch([ |
| | | () => props.isSelectInput, |
| | | () => props.searchVal, |
| | | ], ([newIsSelectInput, newSearchVal]) => { |
| | | if (newIsSelectInput) { |
| | | translateY.value = screenHeight * twoSlidePosition.value |
| | | } |
| | | |
| | | if (!newIsSelectInput && !newSearchVal) { |
| | | translateY.value = screenHeight * initialPosition.value |
| | | } |
| | | }) |
| | | |
| | | // 获取屏幕高度 |
| | | onMounted(() => { |
| | | const info = uni.getSystemInfoSync() |
| | | screenHeight = info.windowHeight |
| | | |
| | | // #ifdef APP-PLUS |
| | | initialPosition.value = 0.8 |
| | | // #endif |
| | | |
| | | // #ifdef H5 |
| | | initialPosition.value = 0.95 |
| | | |
| | | if (screenHeight < 500) { |
| | | initialPosition.value = 0.86 |
| | | } |
| | | |
| | | if (screenHeight > 575) { |
| | | initialPosition.value = 0.85 |
| | | } |
| | | |
| | | if (screenHeight > 642) { |
| | | initialPosition.value = 0.865 |
| | | } |
| | | // #endif |
| | | |
| | | translateY.value = screenHeight * initialPosition.value |
| | | }) |
| | | |
| | | // 拖拽开始 |
| | | const onTouchStart = (e) => { |
| | | // 只在拖拽时,阻止页面滚动 |
| | | startY.value = e.touches[0].clientY |
| | | currentY.value = translateY.value |
| | | isDragging.value = true |
| | | } |
| | | |
| | | // 拖拽移动 |
| | | const onTouchMove = (e) => { |
| | | // 只在拖拽时,阻止页面滚动 |
| | | if (isDragging.value) { |
| | | e.preventDefault() // 阻止滚动行为 |
| | | e.stopPropagation() // 阻止事件冒泡 |
| | | } |
| | | |
| | | const delta = e.touches[0].clientY - startY.value |
| | | let nextY = currentY.value + delta |
| | | |
| | | // 限制拖拽范围 [0, 90% 屏幕高度] |
| | | nextY = Math.min(screenHeight * (1 - twoSlidePosition.value), Math.max(0, nextY)) |
| | | |
| | | translateY.value = nextY |
| | | } |
| | | |
| | | // 拖拽结束后自动吸附 |
| | | const onTouchEnd = () => { |
| | | isDragging.value = false |
| | | const percentFromTop = 100 - (translateY.value / screenHeight) * 100 |
| | | |
| | | if (percentFromTop < 20) translateY.value = screenHeight * initialPosition.value |
| | | else if (percentFromTop < 40) translateY.value = screenHeight * oneSlidePosition.value |
| | | else if (percentFromTop < 75) translateY.value = screenHeight * oneSlidePosition.value |
| | | else if (percentFromTop < 90) translateY.value = screenHeight * twoSlidePosition.value |
| | | else translateY.value = screenHeight * twoSlidePosition.value |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .panel-container { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | width: 100%; |
| | | height: 90vh; |
| | | background: #fff; |
| | | border-top-left-radius: 20rpx; |
| | | border-top-right-radius: 20rpx; |
| | | box-shadow: 0 -4rpx 12rpx rgba(0, 0, 0, 0.15); |
| | | display: flex; |
| | | flex-direction: column; |
| | | z-index: 997; |
| | | touch-action: none; |
| | | /* 禁止默认的滚动行为 */ |
| | | } |
| | | |
| | | .drag-bar { |
| | | width: 80rpx; |
| | | height: 8rpx; |
| | | background: #ccc; |
| | | border-radius: 4rpx; |
| | | margin: 16rpx auto; |
| | | } |
| | | |
| | | .search-box { |
| | | padding: 0 24rpx; |
| | | margin-bottom: 12rpx; |
| | | border-radius: 40rpx; |
| | | transition: backdrop-filter 0.3s ease, background 0.3s ease; |
| | | } |
| | | |
| | | .search-input { |
| | | width: 100%; |
| | | height: 80rpx; |
| | | border-radius: 40rpx; |
| | | background: #f2f2f2; |
| | | padding: 0 24rpx; |
| | | font-size: 28rpx; |
| | | border: none; |
| | | outline: none; |
| | | } |
| | | |
| | | .panel-content { |
| | | flex: 1; |
| | | padding: 20rpx; |
| | | } |
| | | |
| | | .dummy-content { |
| | | text-align: center; |
| | | color: #999; |
| | | margin-top: 100rpx; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- |
| | | * @Author : yuan |
| | | * @Date : 2025-12-03 14:20:57 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-20 16:49:02 |
| | | * @FilePath : \src\pages\map\index.vue |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-12-03 14:20:57 |
| | | --> |
| | | <template> |
| | | <view class="page-wrap"> |
| | | <WebViewPlus :src="`${viewUrl}`" @webMessage="onPostMessage" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getWebViewUrl } from "@/utils/index.js"; |
| | | import WebViewPlus from "@/components/WebViewPlus.vue"; |
| | | import { onHide, onShow } from "@dcloudio/uni-app"; |
| | | // const viewUrl = getWebViewUrl("/defaultMap"); |
| | | |
| | | let envParam = ""; |
| | | // #ifdef WEB |
| | | envParam = "true"; |
| | | // #endif |
| | | // #ifdef APP-PLUS |
| | | envParam = "false"; |
| | | // #endif |
| | | |
| | | const updateKey = ref(0); |
| | | const viewUrl = computed(() => { |
| | | return getWebViewUrl("/defaultMap", { |
| | | isWeb: envParam, |
| | | updateKey: updateKey.value, |
| | | }); |
| | | }); |
| | | |
| | | const onPostMessage = (data) => { |
| | | // #ifdef MP-WEIXIN |
| | | if (data.type === "scanCode") { |
| | | } else if (data.type === "jumpAddWork") { |
| | | } else if (data.type === "jumpMapNav") { |
| | | //事件导航 |
| | | } else if (data.type === "workid") { |
| | | //事件详情 |
| | | } |
| | | // #endif |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | if (data.type === "scanCode") { |
| | | uni.navigateTo({ |
| | | url: "/subPackages/qrCode/index", |
| | | }); |
| | | } else if (data.type === "jumpAddWork") { |
| | | //新建任务 |
| | | const encodedData = encodeURIComponent(JSON.stringify(data.rowItem)); |
| | | uni.setStorageSync("webview_params", encodedData); |
| | | uni.navigateTo({ |
| | | url: `/subPackages/taskDetail/addTask/index`, |
| | | }); |
| | | } else if (data.type === "jumpMapNav") { |
| | | //事件导航 |
| | | uni.navigateTo({ |
| | | url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`, |
| | | }); |
| | | } else if (data.type === "workid") { |
| | | //事件详情 |
| | | uni.navigateTo({ |
| | | url: `/subPackages/workDetail/index?eventNum=${data.eventNum}`, |
| | | }); |
| | | } |
| | | // #endif |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // #ifndef MP-WEIXIN |
| | | |
| | | // #endif |
| | | }); |
| | | |
| | | onHide(() => { |
| | | updateKey.value = updateKey.value + 1; |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .page-wrap { |
| | | font-size: 20px; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 我的 --> |
| | | <template> |
| | | <view class="page-wrap"> |
| | | <view class="userBox"> |
| | | <view class="flex items-center pb-30rpx pl-30rpx pr-20rpx"> |
| | | <view class="mr-20rpx"> |
| | | <u-avatar :src="user.avatar" size="70" /> |
| | | </view> |
| | | <view class="flex-1"> |
| | | <view class="userName">{{ userStore?.userInfo?.nick_name }}</view> |
| | | <view class="departs"> |
| | | <image |
| | | src="https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/mobile.svg" |
| | | alt="" |
| | | /> |
| | | <span>{{ user.deptName }}</span> |
| | | </view> |
| | | </view> |
| | | <view class="rightLogo"> |
| | | <image |
| | | src="https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/logo2.png" |
| | | alt="" |
| | | /> |
| | | </view> |
| | | </view> |
| | | <view class="personalInformation"> |
| | | <div class="message"> |
| | | <div class="messagebox">个人信息</div> |
| | | <div class="editInfo" @click="handelEdit(1)"> |
| | | 点击编辑 |
| | | <image :src="rightImage" alt="" /> |
| | | </div> |
| | | </div> |
| | | <div class="passwordBox"> |
| | | <div class="messagebox">修改密码</div> |
| | | <div class="editInfo" @click="handelEdit(2)"> |
| | | 点击编辑 |
| | | <image :src="rightImage" alt="" /> |
| | | </div> |
| | | </div> |
| | | </view> |
| | | |
| | | <view class="mt-20rpx"> |
| | | <div class="goOutStyle" @click="logOut">退出登录</div> |
| | | </view> |
| | | <div class="bottomLogo"> |
| | | <image :src="logoImage" alt="" /> |
| | | </div> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getAssetsImage } from "@/utils/index.js"; |
| | | import { getUserInfo } from "@/api/user/index.js"; |
| | | import { useClipboard } from "@/hooks"; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { getDeviceRegionApi } from "@/api/map.js"; |
| | | |
| | | const { setClipboardData, getClipboardData } = useClipboard(); |
| | | |
| | | const rightImage = getAssetsImage("/images/user/rightBtn.svg"); |
| | | const logoImage = getAssetsImage("/images/user/logo1.png"); |
| | | |
| | | const userStore = useUserStore(); |
| | | const user = ref(""); |
| | | const getUserInfoData = () => { |
| | | getUserInfo().then((res) => { |
| | | user.value = res.data.data; |
| | | }); |
| | | }; |
| | | |
| | | function logOut() { |
| | | userStore.setUserInfo(null); |
| | | uni.reLaunch({ |
| | | url: "/pages/login/index", |
| | | }); |
| | | } |
| | | |
| | | function getDeviceRegion() { |
| | | getDeviceRegionApi().then((res) => {}); |
| | | } |
| | | const handelEdit = (val) => { |
| | | if (val === 1) { |
| | | uni.navigateTo({ |
| | | url: `/subPackages/userDetail/infos/index`, |
| | | }); |
| | | } else { |
| | | uni.navigateTo({ |
| | | url: `/subPackages/userDetail/password/index`, |
| | | }); |
| | | } |
| | | }; |
| | | onShow(() => { |
| | | getUserInfoData(); |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | |
| | | // #endif |
| | | }); |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .page-wrap { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | .userBox { |
| | | padding-top: 88rpx; |
| | | } |
| | | .userName { |
| | | font-weight: 700; |
| | | font-size: 36rpx; |
| | | color: #000000; |
| | | } |
| | | |
| | | .departs { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-top: 22rpx; |
| | | |
| | | image { |
| | | width: 28rpx; |
| | | height: 28rpx; |
| | | } |
| | | |
| | | span { |
| | | font-family: "Source Han Sans CN"; |
| | | font-weight: 400; |
| | | font-size: 28rpx; |
| | | color: rgba(0, 0, 0, 0.6); |
| | | margin-left: 6rpx; |
| | | } |
| | | } |
| | | |
| | | .rightLogo { |
| | | width: 200rpx; |
| | | height: 80rpx; |
| | | |
| | | image { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .bottomLogo { |
| | | position: absolute; |
| | | bottom: 50rpx; |
| | | left: 0; |
| | | right: 0; |
| | | margin: 0 auto; |
| | | text-align: center; |
| | | |
| | | image { |
| | | width: 128rpx; |
| | | height: 52rpx; |
| | | } |
| | | } |
| | | |
| | | .goOutStyle { |
| | | width: 590rpx; |
| | | height: 76rpx; |
| | | background: #1d6fe9; |
| | | border-radius: 40rpx; |
| | | font-family: "Source Han Sans CN"; |
| | | font-weight: 400; |
| | | font-size: 28rpx; |
| | | color: #ffffff; |
| | | text-align: center; |
| | | line-height: 76rpx; |
| | | margin: auto; |
| | | margin-top: 114rpx; |
| | | } |
| | | |
| | | .personalInformation { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 0 24rpx; |
| | | |
| | | .message, |
| | | .passwordBox { |
| | | width: 340rpx; |
| | | height: 160rpx; |
| | | |
| | | .messagebox { |
| | | padding: 20rpx 24rpx; |
| | | font-family: "Source Han Sans CN"; |
| | | font-weight: 500; |
| | | font-size: 28rpx; |
| | | color: #000000; |
| | | } |
| | | |
| | | .editInfo { |
| | | padding: 20rpx 24rpx; |
| | | color: rgba(0, 0, 0, 0.5); |
| | | font-family: "Source Han Sans CN"; |
| | | font-weight: 400; |
| | | font-size: 24rpx; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | image { |
| | | width: 28rpx; |
| | | height: 28rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .message { |
| | | background: url(https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/info.png) |
| | | no-repeat center; |
| | | background-size: 100% 100%; |
| | | } |
| | | |
| | | .passwordBox { |
| | | background: url(https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/images/user/password.png) |
| | | no-repeat center; |
| | | background-size: 100% 100%; |
| | | } |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="eventTickets"> |
| | | 语音通话 |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup></script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .eventTickets { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="eventTickets"> |
| | | 工单 |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .eventTickets { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| New file |
| | |
| | | import setupI18n from "@/locales" |
| | | import setupStore from "@/store" |
| | | import setupRequest from "@/utils/request" |
| | | import setupPermission from "./permission" |
| | | import setupUI from "./ui" |
| | | |
| | | export default { |
| | | install (app) { |
| | | // UI扩展配置 |
| | | setupUI(app) |
| | | // 状态管理 |
| | | setupStore(app) |
| | | // 国际化 |
| | | setupI18n(app) |
| | | // 路由拦截 |
| | | setupPermission() |
| | | // 网络请求 |
| | | setupRequest() |
| | | } |
| | | } |
| New file |
| | |
| | | import { |
| | | ERROR404_PATH, |
| | | isPathExists, |
| | | LOGIN_PATH, |
| | | removeQueryString, |
| | | routes |
| | | } from "@/router" |
| | | import {useUserStore} from "@/store/index.js"; |
| | | |
| | | // 白名单路由 |
| | | const whiteList = ["/"] |
| | | routes.forEach(item => { |
| | | if (item.needLogin !== true) { |
| | | whiteList.push(item.path) |
| | | } |
| | | }) |
| | | |
| | | /** |
| | | * 权限校验 |
| | | * @param {string} path |
| | | * @returns {boolean} 是否有权限 |
| | | */ |
| | | export function hasPerm (path = "") { |
| | | if (!isPathExists(path) && path !== "/") { |
| | | uni.redirectTo({ |
| | | url: ERROR404_PATH |
| | | }) |
| | | return false |
| | | } |
| | | // 在白名单中或有token,直接放行 |
| | | const hasPermission = whiteList.includes(removeQueryString(path)) || useUserStore().$state.userInfo.access_token |
| | | if (!hasPermission) { |
| | | // 将用户的目标路径传递过去,这样可以实现用户登录之后,直接跳转到目标页面 |
| | | uni.redirectTo({ |
| | | url: `${LOGIN_PATH}?redirect=${encodeURIComponent(path)}` |
| | | }) |
| | | } |
| | | return hasPermission |
| | | } |
| | | |
| | | function setupPermission () { |
| | | // 注意:拦截uni.switchTab本身没有问题。但是在微信小程序端点击tabbar的底层逻辑并不是触发uni.switchTab。 |
| | | // 所以误认为拦截无效,此类场景的解决方案是在tabbar页面的页面生命周期onShow中处理。 |
| | | ;["navigateTo", "redirectTo", "reLaunch", "switchTab"].forEach(item => { |
| | | // https://uniapp.dcloud.net.cn/api/interceptor.html |
| | | uni.addInterceptor(item, { |
| | | // 页面跳转前进行拦截, invoke根据返回值进行判断是否继续执行跳转 |
| | | invoke (args) { |
| | | // args为所拦截api中的参数,比如拦截的是uni.redirectTo(OBJECT),则args对应的是OBJECT参数 |
| | | return hasPerm(args.url) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | export default setupPermission |
| New file |
| | |
| | | import uviewPlus, { |
| | | setConfig |
| | | } from "uview-plus" |
| | | |
| | | function setupUI(app) { |
| | | // 下面的在特殊场景下才需要配置,通常不用配置即可直接使用uview-plus框架。 |
| | | // 调用setConfig方法,方法内部会进行对象属性深度合并,可以放心嵌套配置 |
| | | // 需要在app.use(uview-plus)之后执行 |
| | | setConfig({ |
| | | // 修改$u.config对象的属性 |
| | | config: { |
| | | // 修改默认单位为rpx,相当于执行 uni.$u.config.unit = 'rpx' |
| | | unit: "rpx" |
| | | }, |
| | | // 修改$u.props对象的属性 |
| | | props: { |
| | | // 修改radio组件的size参数的默认值,相当于执行 uni.$u.props.radio.size = 30 |
| | | radio: { |
| | | // size: 20 |
| | | } |
| | | // 其他组件属性配置 |
| | | // ...... |
| | | } |
| | | }) |
| | | |
| | | app.use(uviewPlus, () => { |
| | | return { |
| | | options: { |
| | | // 修改config对象的属性 |
| | | config: { |
| | | customIcon: { |
| | | family: 'xyicon', |
| | | url: 'https://at.alicdn.com/t/c/font_5036193_7g86rzw8srl.ttf?t=1760003919145' |
| | | }, |
| | | customIcons: { |
| | | 'tuceng': '\uea2d', |
| | | 'dingwei': '\ue610', |
| | | }, |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | export default setupUI |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:55:05 |
| | | * @FilePath : \src\router\index.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import pagesJson from "@/pages.json" |
| | | |
| | | // 路径常量 |
| | | export const HOME_PATH = "/pages/map/index" |
| | | export const LOGIN_PATH = "/pages/login/index" |
| | | export const ERROR404_PATH = "/pages/common/404/index" |
| | | |
| | | /** |
| | | * 解析路由地址 |
| | | * @param {object} pagesJson |
| | | * @returns [{"path": "/pages/tab/map/index","needLogin": false},...] |
| | | */ |
| | | function parseRoutes (pagesJson = {}) { |
| | | if (!pagesJson.pages) { |
| | | pagesJson.pages = [] |
| | | } |
| | | if (!pagesJson.subPackages) { |
| | | pagesJson.subPackages = [] |
| | | } |
| | | |
| | | function parsePages (pages = [], rootPath = "") { |
| | | const routes = [] |
| | | for (let i = 0; i < pages.length; i++) { |
| | | routes.push({ |
| | | path: rootPath ? `/${rootPath}/${pages[i].path}` : `/${pages[i].path}`, |
| | | needLogin: pages[i].needLogin === true |
| | | }) |
| | | } |
| | | return routes |
| | | } |
| | | |
| | | function parseSubPackages (subPackages = []) { |
| | | const routes = [] |
| | | for (let i = 0; i < subPackages.length; i++) { |
| | | routes.push(...parsePages(subPackages[i].pages, subPackages[i].root)) |
| | | } |
| | | return routes |
| | | } |
| | | |
| | | return [ |
| | | ...parsePages(pagesJson.pages), |
| | | ...parseSubPackages(pagesJson.subPackages) |
| | | ] |
| | | } |
| | | export const routes = parseRoutes(pagesJson) |
| | | |
| | | /** |
| | | * 当前路由 |
| | | * @returns {string} 当前路由 |
| | | */ |
| | | export function currentRoute () { |
| | | // getCurrentPages() 至少有1个元素,所以不再额外判断 |
| | | const pages = getCurrentPages() |
| | | const currentPage = pages[pages.length - 1] |
| | | return currentPage?.$page?.fullPath || currentPage.route |
| | | } |
| | | |
| | | /** |
| | | * 去除查询字符串 |
| | | * @param {string} path |
| | | * @returns {string} 去除查询字符串后的路径 |
| | | */ |
| | | export function removeQueryString (path = "") { |
| | | return path.split("?")[0] |
| | | } |
| | | |
| | | /** |
| | | * 路径是否存在 |
| | | * @param {string} path |
| | | * @returns {boolean} 路径是否存在 |
| | | */ |
| | | export function isPathExists (path = "") { |
| | | const cleanPath = removeQueryString(path) |
| | | return routes.some(item => item.path === cleanPath) |
| | | } |
| | | |
| | | /** |
| | | * 是否是tabbar页面路径 |
| | | * @param {string} path |
| | | * @returns {boolean} 是否是tabbar页面 |
| | | */ |
| | | export function isTabBarPath (path = "") { |
| | | const cleanPath = removeQueryString(path) |
| | | return ( |
| | | pagesJson.tabBar?.list?.some(item => `/${item.pagePath}` === cleanPath) === |
| | | true |
| | | ) |
| | | } |
| New file |
| | |
| | | @font-face { |
| | | font-family: "Source Han Sans CN"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/SourceHanSansCN-Regular.woff2") |
| | | format("opentype"); |
| | | font-weight: 400; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| | | |
| | | @font-face { |
| | | font-family: "Source Han Sans CN"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/SourceHanSansCN-Bold.woff2") |
| | | format("opentype"); |
| | | font-weight: 700; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| | | |
| | | @font-face { |
| | | font-family: "Segoe UI"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/SourceHanSansCN-Regular.woff2") |
| | | format("opentype"); |
| | | font-weight: 400; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| | | |
| | | @font-face { |
| | | font-family: "Segoe UI"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/SourceHanSansCN-Bold.woff2") |
| | | format("opentype"); |
| | | font-weight: 700; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| | | |
| | | /* 额外的标题字体 */ |
| | | @font-face { |
| | | font-family: "YouSheBiaoTiHei"; |
| | | src: url("https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ztzf_app_assets/fonts/YouSheBiaoTiHei.TTF") |
| | | format("truetype"); |
| | | font-weight: normal; |
| | | font-style: normal; |
| | | font-display: swap; |
| | | } |
| New file |
| | |
| | | <svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316217"> |
| | | <g id="图标"> |
| | | <circle id="bg" cx="28" cy="28" r="25.5" fill="#1D6FE9" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | <g id="Frame"> |
| | | <path id="Vector" d="M29.051 17.3062C29.1972 17.3062 29.3373 17.3642 29.4407 17.4675C29.544 17.5709 29.6021 17.711 29.6021 17.8572V26.6735H38.4184C38.5645 26.6735 38.7047 26.7316 38.808 26.8349C38.9114 26.9382 38.9694 27.0784 38.9694 27.2245V28.3266C38.9694 28.4727 38.9114 28.6129 38.808 28.7162C38.7047 28.8195 38.5645 28.8776 38.4184 28.8776H29.6021V37.6939C29.6021 37.84 29.544 37.9802 29.4407 38.0835C29.3373 38.1869 29.1972 38.2449 29.051 38.2449H27.949C27.8029 38.2449 27.6627 38.1869 27.5594 38.0835C27.456 37.9802 27.398 37.84 27.398 37.6939V28.8776H18.5817C18.4355 28.8776 18.2954 28.8195 18.192 28.7162C18.0887 28.6129 18.0306 28.4727 18.0306 28.3266V27.2245C18.0306 27.0784 18.0887 26.9382 18.192 26.8349C18.2954 26.7316 18.4355 26.6735 18.5817 26.6735H27.398V17.8572C27.398 17.711 27.456 17.5709 27.5594 17.4675C27.6627 17.3642 27.8029 17.3062 27.949 17.3062H29.051Z" fill="white" stroke="white" stroke-width="0.4"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316217"> |
| | | <g id="图标"> |
| | | <circle id="bg" cx="28" cy="28" r="25.5" fill="#1D6FE9" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | <g id="Frame"> |
| | | <path id="Vector" d="M29.051 17.3062C29.1972 17.3062 29.3373 17.3642 29.4407 17.4675C29.544 17.5709 29.6021 17.711 29.6021 17.8572V26.6735H38.4184C38.5645 26.6735 38.7047 26.7316 38.808 26.8349C38.9114 26.9382 38.9694 27.0784 38.9694 27.2245V28.3266C38.9694 28.4727 38.9114 28.6129 38.808 28.7162C38.7047 28.8195 38.5645 28.8776 38.4184 28.8776H29.6021V37.6939C29.6021 37.84 29.544 37.9802 29.4407 38.0835C29.3373 38.1869 29.1972 38.2449 29.051 38.2449H27.949C27.8029 38.2449 27.6627 38.1869 27.5594 38.0835C27.456 37.9802 27.398 37.84 27.398 37.6939V28.8776H18.5817C18.4355 28.8776 18.2954 28.8195 18.192 28.7162C18.0887 28.6129 18.0306 28.4727 18.0306 28.3266V27.2245C18.0306 27.0784 18.0887 26.9382 18.192 26.8349C18.2954 26.7316 18.4355 26.6735 18.5817 26.6735H27.398V17.8572C27.398 17.711 27.456 17.5709 27.5594 17.4675C27.6627 17.3642 27.8029 17.3062 27.949 17.3062H29.051Z" fill="white" stroke="white" stroke-width="0.4"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316217"> |
| | | <g id="图标"> |
| | | <circle id="bg" cx="28" cy="28" r="25.5" fill="#1D6FE9" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | <g id="Frame"> |
| | | <path id="Vector" d="M29.051 17.3062C29.1972 17.3062 29.3373 17.3642 29.4407 17.4675C29.544 17.5709 29.6021 17.711 29.6021 17.8572V26.6735H38.4184C38.5645 26.6735 38.7047 26.7316 38.808 26.8349C38.9114 26.9382 38.9694 27.0784 38.9694 27.2245V28.3266C38.9694 28.4727 38.9114 28.6129 38.808 28.7162C38.7047 28.8195 38.5645 28.8776 38.4184 28.8776H29.6021V37.6939C29.6021 37.84 29.544 37.9802 29.4407 38.0835C29.3373 38.1869 29.1972 38.2449 29.051 38.2449H27.949C27.8029 38.2449 27.6627 38.1869 27.5594 38.0835C27.456 37.9802 27.398 37.84 27.398 37.6939V28.8776H18.5817C18.4355 28.8776 18.2954 28.8195 18.192 28.7162C18.0887 28.6129 18.0306 28.4727 18.0306 28.3266V27.2245C18.0306 27.0784 18.0887 26.9382 18.192 26.8349C18.2954 26.7316 18.4355 26.6735 18.5817 26.6735H27.398V17.8572C27.398 17.711 27.456 17.5709 27.5594 17.4675C27.6627 17.3642 27.8029 17.3062 27.949 17.3062H29.051Z" fill="white" stroke="white" stroke-width="0.4"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Frame" clip-path="url(#clip0_2193_2310)"> |
| | | <path id="Vector" d="M9.91638 3.74371C9.92985 3.74371 9.93856 3.74689 9.9447 3.75055V3.74957L14.1088 6.24371H14.1097C14.1278 6.25464 14.1342 6.27141 14.1342 6.28375V21.0543C14.134 21.0767 14.1164 21.0972 14.0883 21.0972C14.0819 21.0972 14.0745 21.0955 14.0677 21.0914L14.0658 21.0904L9.89587 18.5728L9.89294 18.5709L9.8783 18.5562C9.87433 18.5491 9.8725 18.5416 9.87244 18.5347V3.78766C9.87244 3.7637 9.8919 3.74371 9.91638 3.74371ZM7.17419 2.97223C7.18018 2.98303 7.18292 2.99144 7.18298 2.99957V18.3658C7.18293 18.3839 7.17326 18.3982 7.16052 18.4058L2.99451 20.897H2.99353C2.97355 20.909 2.94565 20.9043 2.93103 20.8804L2.92908 20.8775C2.92878 20.8769 2.92782 20.8752 2.92712 20.8726C2.92624 20.8693 2.92615 20.8639 2.92615 20.857V5.52887C2.92615 5.52001 2.92792 5.51161 2.93201 5.50446L2.94861 5.48785L7.1156 2.96051C7.13758 2.94718 7.16169 2.95431 7.17419 2.97223ZM21.0687 2.97321C21.0742 2.98351 21.0765 2.99172 21.0765 2.99957V18.3658C21.0765 18.3749 21.0746 18.3834 21.0707 18.3902L21.0551 18.4058L16.8881 20.897H16.8871C16.8671 20.9089 16.8392 20.9043 16.8246 20.8804L16.8236 20.8775L16.8217 20.8726C16.8208 20.8693 16.8197 20.8641 16.8197 20.857V5.53473C16.8199 5.52179 16.8226 5.51142 16.8265 5.50446C16.8303 5.4978 16.8359 5.49264 16.8422 5.48883L21.0092 2.96051C21.0316 2.9469 21.0565 2.9545 21.0687 2.97321Z" stroke="#8C8C8C" stroke-width="1.3"/> |
| | | </g> |
| | | <defs> |
| | | <clipPath id="clip0_2193_2310"> |
| | | <rect width="24" height="24" fill="white"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Frame" clip-path="url(#clip0_2193_2351)"> |
| | | <path id="Vector" d="M2.60857 4.9336L6.7781 2.40469C7.10623 2.20547 7.53279 2.3086 7.73201 2.63672C7.79763 2.74688 7.83279 2.8711 7.83279 3V18.3656C7.83279 18.6094 7.70622 18.8367 7.49529 18.9633L3.3281 21.4547C2.99998 21.6516 2.57341 21.5461 2.37419 21.2156C2.30857 21.1078 2.27576 20.9836 2.27576 20.857V5.52891C2.27576 5.28516 2.40232 5.06016 2.60857 4.9336ZM16.5047 4.9336L20.6719 2.40469C21 2.20547 21.4265 2.3086 21.6258 2.63672C21.6914 2.74688 21.7265 2.8711 21.7265 3V18.3656C21.7265 18.6094 21.6 18.8367 21.389 18.9633L17.2218 21.4547C16.8937 21.6516 16.4672 21.5461 16.2679 21.2156C16.2023 21.1078 16.1695 20.9836 16.1695 20.857V5.52891C16.1719 5.28516 16.2961 5.06016 16.5047 4.9336ZM10.2773 3.19219L14.4469 5.68829C14.6554 5.81485 14.7843 6.03985 14.7843 6.2836V21.0539C14.7843 21.4383 14.4726 21.7477 14.0883 21.7477C13.9617 21.7477 13.8375 21.7125 13.7297 21.6469L9.56013 19.1297C9.35154 19.0055 9.22263 18.7781 9.22263 18.5344V3.7875C9.22263 3.40313 9.53435 3.09375 9.91638 3.09375C10.0429 3.09375 10.1672 3.12657 10.2773 3.19219Z" fill="#1D6FE9"/> |
| | | </g> |
| | | <defs> |
| | | <clipPath id="clip0_2193_2351"> |
| | | <rect width="24" height="24" fill="white"/> |
| | | </clipPath> |
| | | </defs> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316224"> |
| | | <g id="Group 1321316110"> |
| | | <path id="Vector" d="M18.0517 2H5.9495C3.7748 2 2 3.95801 2 6.35412V16.6459C2 19.0469 3.77117 21 5.9495 21H18.0517C20.2264 21 22 19.042 22 16.6459V6.36023C22 3.95311 20.2288 2 18.0517 2ZM20.5502 16.6459C20.5502 18.2368 19.429 19.5315 18.0517 19.5315H5.9495C4.57098 19.5315 3.4498 18.2368 3.4498 16.6459V6.36023C3.4498 4.76935 4.57098 3.47462 5.9495 3.47462H18.0517C19.429 3.47462 20.5502 4.76935 20.5502 6.36023V16.6459Z" fill="#8C8C8C"/> |
| | | <path id="Vector_2" d="M9.5048 6.51704L7.3727 8.75839L6.45271 7.80389C6.38958 7.73887 6.31426 7.68693 6.23106 7.65102C6.14786 7.61512 6.0584 7.59595 5.96779 7.59461C5.87719 7.59328 5.7872 7.6098 5.70298 7.64324C5.61876 7.67668 5.54194 7.72639 5.47693 7.78951C5.41192 7.85264 5.35997 7.92795 5.32406 8.01116C5.28816 8.09436 5.26899 8.18382 5.26765 8.27442C5.26632 8.36503 5.28284 8.45502 5.31628 8.53924C5.34973 8.62346 5.39943 8.70027 5.46256 8.76529L6.88166 10.235C6.94604 10.3013 7.0231 10.354 7.10824 10.3899C7.19338 10.4259 7.28488 10.4444 7.37731 10.4443C7.4705 10.445 7.56288 10.4268 7.64885 10.3908C7.73483 10.3549 7.81263 10.3019 7.87756 10.235L10.5053 7.47499C10.6314 7.34231 10.6997 7.16497 10.695 6.98198C10.6904 6.79899 10.6133 6.62533 10.4806 6.49921C10.3479 6.3731 10.1706 6.30485 9.98757 6.30949C9.80458 6.31412 9.63092 6.39126 9.5048 6.52394V6.51704ZM17.3168 7.68314H12.3131C12.1301 7.68314 11.9546 7.75584 11.8252 7.88524C11.6958 8.01464 11.6231 8.19014 11.6231 8.37314C11.6231 8.55614 11.6958 8.73164 11.8252 8.86104C11.9546 8.99044 12.1301 9.06314 12.3131 9.06314H17.3168C17.4998 9.06314 17.6753 8.99044 17.8047 8.86104C17.9341 8.73164 18.0068 8.55614 18.0068 8.37314C18.0068 8.19014 17.9341 8.01464 17.8047 7.88524C17.6753 7.75584 17.4998 7.68314 17.3168 7.68314ZM17.3168 13.555H12.3131C12.1301 13.555 11.9546 13.6277 11.8252 13.7571C11.6958 13.8865 11.6231 14.062 11.6231 14.245C11.6231 14.428 11.6958 14.6035 11.8252 14.7329C11.9546 14.8623 12.1301 14.935 12.3131 14.935H17.3168C17.4998 14.935 17.6753 14.8623 17.8047 14.7329C17.9341 14.6035 18.0068 14.428 18.0068 14.245C18.0068 14.062 17.9341 13.8865 17.8047 13.7571C17.6753 13.6277 17.4998 13.555 17.3168 13.555ZM7.97875 11.4252C7.48997 11.4252 7.01216 11.5702 6.60575 11.8417C6.19934 12.1133 5.88258 12.4993 5.69553 12.9508C5.50848 13.4024 5.45953 13.8993 5.55489 14.3787C5.65025 14.8581 5.88562 15.2985 6.23125 15.6441C6.57687 15.9897 7.01722 16.2251 7.49662 16.3205C7.97601 16.4158 8.47292 16.3669 8.9245 16.1798C9.37608 15.9928 9.76205 15.676 10.0336 15.2696C10.3052 14.8632 10.4501 14.3854 10.4501 13.8966C10.4492 13.2414 10.1885 12.6134 9.72525 12.1501C9.26198 11.6868 8.63392 11.4262 7.97875 11.4252ZM7.97875 14.9902C7.76291 14.9902 7.55191 14.9262 7.37243 14.8063C7.19296 14.6864 7.05308 14.5159 6.97048 14.3165C6.88788 14.1171 6.86627 13.8977 6.90838 13.686C6.95049 13.4743 7.05443 13.2798 7.20705 13.1272C7.35968 12.9746 7.55414 12.8706 7.76584 12.8285C7.97754 12.7864 8.19698 12.808 8.3964 12.8906C8.59581 12.9732 8.76626 13.1131 8.88618 13.2926C9.0061 13.472 9.0701 13.683 9.0701 13.8989C9.06889 14.1877 8.95345 14.4644 8.74898 14.6684C8.54451 14.8725 8.26761 14.9873 7.97875 14.9879V14.9902Z" fill="#8C8C8C"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316223"> |
| | | <g id="Frame"> |
| | | <path id="Vector" d="M18.0517 2H5.9495C3.7748 2 2 3.95801 2 6.35412V16.6459C2 19.0469 3.77117 21 5.9495 21H18.0517C20.2264 21 22 19.042 22 16.6459V6.36023C22 3.95311 20.2288 2 18.0517 2ZM20.5502 16.6459C20.5502 18.2368 19.429 19.5315 18.0517 19.5315H5.9495C4.57098 19.5315 3.4498 18.2368 3.4498 16.6459V6.36023C3.4498 4.76935 4.57098 3.47462 5.9495 3.47462H18.0517C19.429 3.47462 20.5502 4.76935 20.5502 6.36023V16.6459Z" fill="#444444"/> |
| | | <path id="Exclude" d="M22 16.9C22 19.1644 20.1644 21 17.9 21H6.1C3.83563 21 2 19.1644 2 16.9V6.1C2 3.83563 3.83563 2 6.1 2H17.9C20.1644 2 22 3.83563 22 6.1V16.9ZM7.97852 11.4248C7.48981 11.4249 7.01181 11.5703 6.60547 11.8418C6.19916 12.1133 5.88233 12.4997 5.69531 12.9512C5.50838 13.4027 5.45935 13.8996 5.55469 14.3789C5.65006 14.8582 5.88585 15.2989 6.23145 15.6445C6.57702 15.99 7.01782 16.225 7.49707 16.3203C7.97634 16.4156 8.47335 16.3667 8.9248 16.1797C9.3762 15.9926 9.76171 15.6758 10.0332 15.2695C10.3048 14.8631 10.4502 14.3853 10.4502 13.8965C10.4493 13.2415 10.1886 12.6136 9.72559 12.1504C9.26232 11.6871 8.63368 11.4257 7.97852 11.4248ZM7.76562 12.8281C7.97733 12.786 8.19707 12.808 8.39648 12.8906C8.59587 12.9732 8.76584 13.1135 8.88574 13.293C9.00555 13.4723 9.07022 13.6828 9.07031 13.8984C9.0691 14.1872 8.95333 14.464 8.74902 14.668C8.54478 14.8718 8.268 14.9874 7.97949 14.9883C7.97895 14.9883 7.97852 14.9887 7.97852 14.9893C7.97852 14.9898 7.97808 14.9902 7.97754 14.9902C7.76211 14.99 7.5512 14.9263 7.37207 14.8066C7.19265 14.6867 7.05329 14.5158 6.9707 14.3164C6.88811 14.117 6.8661 13.8972 6.9082 13.6855C6.95036 13.474 7.05449 13.2795 7.20703 13.127C7.35961 12.9744 7.55403 12.8702 7.76562 12.8281ZM12.3135 13.5547C12.1305 13.5547 11.9546 13.6275 11.8252 13.7568C11.6958 13.8862 11.623 14.0621 11.623 14.2451C11.6231 14.4281 11.6958 14.604 11.8252 14.7334C11.9546 14.8627 12.1306 14.9346 12.3135 14.9346H17.3164C17.4993 14.9346 17.6753 14.8627 17.8047 14.7334C17.9341 14.604 18.0068 14.4281 18.0068 14.2451C18.0068 14.0621 17.9341 13.8862 17.8047 13.7568C17.6753 13.6275 17.4993 13.5547 17.3164 13.5547H12.3135ZM9.9873 6.30957C9.80571 6.31424 9.63341 6.3907 9.50759 6.52159C9.50661 6.5226 9.50488 6.52192 9.50488 6.52051C9.50488 6.5191 9.50316 6.51841 9.50219 6.51943L8.00092 8.09842C7.65871 8.45834 7.08544 8.46019 6.74091 8.10249L6.45312 7.80371C6.39011 7.73881 6.31447 7.68727 6.23145 7.65137C6.14824 7.61546 6.05838 7.59606 5.96777 7.59473C5.87718 7.59339 5.78734 7.61012 5.70312 7.64355C5.61892 7.67699 5.54157 7.72595 5.47656 7.78906C5.41165 7.85209 5.36012 7.9277 5.32422 8.01074C5.28831 8.09394 5.26891 8.18381 5.26758 8.27441C5.26624 8.36498 5.28299 8.45487 5.31641 8.53906C5.34985 8.62329 5.39976 8.70061 5.46289 8.76562L6.88184 10.2354C6.94617 10.3015 7.02337 10.3537 7.1084 10.3896C7.19343 10.4255 7.28466 10.4444 7.37695 10.4443C7.47005 10.445 7.56254 10.4265 7.64844 10.3906C7.73442 10.3547 7.813 10.3022 7.87793 10.2354L10.5049 7.47461C10.6309 7.34204 10.6998 7.16526 10.6953 6.98242C10.6907 6.79943 10.6131 6.62514 10.4805 6.49902C10.3478 6.373 10.1702 6.30494 9.9873 6.30957ZM12.3135 7.68359C12.1306 7.68359 11.9546 7.75551 11.8252 7.88477C11.6958 8.01414 11.6231 8.19008 11.623 8.37305C11.623 8.55605 11.6958 8.73193 11.8252 8.86133C11.9546 8.99064 12.1305 9.06348 12.3135 9.06348H17.3164C17.4993 9.06348 17.6753 8.99065 17.8047 8.86133C17.9341 8.73193 18.0068 8.55605 18.0068 8.37305C18.0068 8.19008 17.9341 8.01414 17.8047 7.88477C17.6753 7.7555 17.4993 7.68359 17.3164 7.68359H12.3135Z" fill="#1D6FE9"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="user"> |
| | | <g id="user_2"> |
| | | <path id="primary" d="M16 7C16 7.79113 15.7654 8.56448 15.3259 9.22228C14.8864 9.88008 14.2616 10.3928 13.5307 10.6955C12.7998 10.9983 11.9956 11.0775 11.2196 10.9231C10.4437 10.7688 9.73098 10.3878 9.17157 9.82843C8.61216 9.26902 8.2312 8.55629 8.07686 7.78036C7.92252 7.00444 8.00173 6.20017 8.30448 5.46927C8.60723 4.73836 9.11992 4.11365 9.77772 3.67412C10.4355 3.2346 11.2089 3 12 3C13.0609 3 14.0783 3.42143 14.8284 4.17157C15.5786 4.92172 16 5.93913 16 7ZM16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19V19C4 19.5304 4.21071 20.0391 4.58579 20.4142C4.96086 20.7893 5.46957 21 6 21H18C18.5304 21 19.0391 20.7893 19.4142 20.4142C19.7893 20.0391 20 19.5304 20 19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15V15Z" stroke="#8C8C8C" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="user"> |
| | | <g id="user_2"> |
| | | <path id="primary" d="M16 7C16 7.79113 15.7654 8.56448 15.3259 9.22228C14.8864 9.88008 14.2616 10.3928 13.5307 10.6955C12.7998 10.9983 11.9956 11.0775 11.2196 10.9231C10.4437 10.7688 9.73098 10.3878 9.17157 9.82843C8.61216 9.26902 8.2312 8.55629 8.07686 7.78036C7.92252 7.00444 8.00173 6.20017 8.30448 5.46927C8.60723 4.73836 9.11992 4.11365 9.77772 3.67412C10.4355 3.2346 11.2089 3 12 3C13.0609 3 14.0783 3.42143 14.8284 4.17157C15.5786 4.92172 16 5.93913 16 7ZM16 15H8C6.93913 15 5.92172 15.4214 5.17157 16.1716C4.42143 16.9217 4 17.9391 4 19C4 19.5304 4.21071 20.0391 4.58579 20.4142C4.96086 20.7893 5.46957 21 6 21H18C18.5304 21 19.0391 20.7893 19.4142 20.4142C19.7893 20.0391 20 19.5304 20 19C20 17.9391 19.5786 16.9217 18.8284 16.1716C18.0783 15.4214 17.0609 15 16 15Z" fill="#1D6FE9" stroke="#1D6FE9" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316220"> |
| | | <g id="Group 1321316218"> |
| | | <path id="Vector" d="M21.9989 6.20825C21.9669 5.55338 21.6873 4.94449 21.2116 4.49381C20.7267 4.03439 20.0844 4 19.4034 4H16.7914L16.7915 2.79167C16.7915 2.5817 16.7037 2.38034 16.5474 2.23187C16.3911 2.08341 16.1792 2 15.9582 2C15.7372 2 15.5252 2.08341 15.3689 2.23187C15.2126 2.38034 15.1248 2.5817 15.1248 2.79167L15.1247 4H8.87489L8.87502 2.79167C8.87502 2.5817 8.78722 2.38034 8.63095 2.23187C8.47467 2.08341 8.26271 2 8.04169 2C7.82068 2 7.60872 2.08341 7.45244 2.23187C7.29616 2.38034 7.20837 2.5817 7.20837 2.79167L7.20823 4H4.60212C3.22092 4 2.07853 4.82277 2.00133 6.15213C2.0004 6.1667 2 6.18127 2 6.19583V18.5118C2 18.5263 2.0004 18.5408 2.00133 18.5555C2.076 19.841 3.16493 20.8908 4.53425 20.9973C4.55692 20.9992 4.57958 21 4.60238 21H19.4036C19.4263 21 19.4489 20.9991 19.4716 20.9973C20.1264 20.9455 20.7412 20.6768 21.2087 20.2381C21.6849 19.7916 21.9656 19.2105 21.9989 18.6021C21.9996 18.5884 22 18.5747 22 18.561V6.24498C21.9999 6.23273 21.9996 6.22048 21.9989 6.20825ZM20.3332 18.5368C20.2991 18.9766 19.8713 19.3641 19.3644 19.4167H4.64132C4.12625 19.3631 3.70439 18.9612 3.66666 18.4864V6.22079C3.70439 5.7392 4.11172 5.36465 4.60225 5.36465H7.20823V6.55215C7.20823 6.76211 7.29603 6.96347 7.45231 7.11194C7.60859 7.26041 7.82055 7.34381 8.04156 7.34381C8.26257 7.34381 8.47453 7.26041 8.63081 7.11194C8.78709 6.96347 8.87489 6.76211 8.87489 6.55215V5.36465H15.1248V6.55215C15.1248 6.76211 15.2126 6.96347 15.3689 7.11194C15.5252 7.26041 15.7372 7.34381 15.9582 7.34381C16.1792 7.34381 16.3911 7.26041 16.5474 7.11194C16.7037 6.96347 16.7915 6.76211 16.7915 6.55215V5.36465H19.4035C19.9032 5.36465 20.3004 5.75098 20.3332 6.26588V18.5368Z" fill="#8C8C8C"/> |
| | | <path id="Vector_2" d="M16.9465 13.9149H7.60278C7.38729 13.9149 7.18063 14.0005 7.02826 14.1529C6.87589 14.3053 6.79028 14.5119 6.79028 14.7274C6.79028 14.9429 6.87589 15.1496 7.02826 15.3019C7.18063 15.4543 7.38729 15.5399 7.60278 15.5399H16.9465C17.162 15.5399 17.3687 15.4543 17.5211 15.3019C17.6734 15.1496 17.759 14.9429 17.759 14.7274C17.759 14.5119 17.6734 14.3053 17.5211 14.1529C17.3687 14.0005 17.162 13.9149 16.9465 13.9149ZM7.5994 11.4774H12.0749C12.1812 11.4774 12.2864 11.4565 12.3846 11.4159C12.4827 11.3752 12.5719 11.3156 12.6471 11.2405C12.7222 11.1653 12.7818 11.0761 12.8225 10.978C12.8631 10.8798 12.8841 10.7746 12.884 10.6683V10.6615C12.884 10.5553 12.8631 10.4501 12.8224 10.3519C12.7818 10.2537 12.7222 10.1645 12.647 10.0894C12.5719 10.0143 12.4827 9.95467 12.3845 9.91401C12.2864 9.87335 12.1812 9.85242 12.0749 9.85242H7.5994C7.38481 9.85242 7.17901 9.93766 7.02727 10.0894C6.87553 10.2411 6.79028 10.4469 6.79028 10.6615V10.6683C6.79028 10.7746 6.81121 10.8798 6.85187 10.9779C6.89254 11.0761 6.95214 11.1653 7.02727 11.2404C7.1024 11.3156 7.1916 11.3752 7.28977 11.4158C7.38793 11.4565 7.49315 11.4774 7.5994 11.4774Z" fill="#8C8C8C"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> |
| | | <g id="Group 1321316221"> |
| | | <g id="Group 1321316219"> |
| | | <path id="Vector" d="M21.9989 6.20825C21.9669 5.55338 21.6873 4.94449 21.2116 4.49381C20.7267 4.03439 20.0844 4 19.4034 4H16.7914L16.7915 2.79167C16.7915 2.5817 16.7037 2.38034 16.5474 2.23187C16.3911 2.08341 16.1792 2 15.9582 2C15.7372 2 15.5252 2.08341 15.3689 2.23187C15.2126 2.38034 15.1248 2.5817 15.1248 2.79167L15.1247 4H8.87489L8.87502 2.79167C8.87502 2.5817 8.78722 2.38034 8.63095 2.23187C8.47467 2.08341 8.26271 2 8.04169 2C7.82068 2 7.60872 2.08341 7.45244 2.23187C7.29616 2.38034 7.20837 2.5817 7.20837 2.79167L7.20823 4H4.60212C3.22092 4 2.07853 4.82277 2.00133 6.15213C2.0004 6.1667 2 6.18127 2 6.19583V18.5118C2 18.5263 2.0004 18.5408 2.00133 18.5555C2.076 19.841 3.16493 20.8908 4.53425 20.9973C4.55692 20.9992 4.57958 21 4.60238 21H19.4036C19.4263 21 19.4489 20.9991 19.4716 20.9973C20.1264 20.9455 20.7412 20.6768 21.2087 20.2381C21.6849 19.7916 21.9656 19.2105 21.9989 18.6021C21.9996 18.5884 22 18.5747 22 18.561V6.24498C21.9999 6.23273 21.9996 6.22048 21.9989 6.20825ZM20.3332 18.5368C20.2991 18.9766 19.8713 19.3641 19.3644 19.4167H4.64132C4.12625 19.3631 3.70439 18.9612 3.66666 18.4864V6.22079C3.70439 5.7392 4.11172 5.36465 4.60225 5.36465H7.20823V6.55215C7.20823 6.76211 7.29603 6.96347 7.45231 7.11194C7.60859 7.26041 7.82055 7.34381 8.04156 7.34381C8.26257 7.34381 8.47453 7.26041 8.63081 7.11194C8.78709 6.96347 8.87489 6.76211 8.87489 6.55215V5.36465H15.1248V6.55215C15.1248 6.76211 15.2126 6.96347 15.3689 7.11194C15.5252 7.26041 15.7372 7.34381 15.9582 7.34381C16.1792 7.34381 16.3911 7.26041 16.5474 7.11194C16.7037 6.96347 16.7915 6.76211 16.7915 6.55215V5.36465H19.4035C19.9032 5.36465 20.3004 5.75098 20.3332 6.26588V18.5368Z" fill="#1D6FE9"/> |
| | | <path id="Exclude" d="M19.5996 4C20.9251 4 22 5.07491 22 6.40039V18.5996C22 19.9251 20.9251 21 19.5996 21H4.40039C3.07491 21 2 19.9251 2 18.5996V6.40039C2 5.07491 3.07491 4 4.40039 4H19.5996ZM7.60254 13.915C7.38718 13.9151 7.18061 14.001 7.02832 14.1533C6.8761 14.3057 6.79004 14.5122 6.79004 14.7275C6.79007 14.9429 6.87605 15.1494 7.02832 15.3018C7.18061 15.454 7.38718 15.5399 7.60254 15.54H16.9463C17.1618 15.54 17.3691 15.4541 17.5215 15.3018C17.6737 15.1494 17.7588 14.9429 17.7588 14.7275C17.7588 14.5122 17.6736 14.3057 17.5215 14.1533C17.3691 14.0009 17.1618 13.915 16.9463 13.915H7.60254ZM7.59961 9.85254C7.38502 9.85254 7.17908 9.9381 7.02734 10.0898C6.87585 10.2415 6.79015 10.4468 6.79004 10.6611V10.668C6.79004 10.774 6.81103 10.8795 6.85156 10.9775C6.8922 11.0757 6.95227 11.1651 7.02734 11.2402C7.10248 11.3154 7.19187 11.3754 7.29004 11.416C7.38815 11.4566 7.49342 11.4775 7.59961 11.4775H12.0752C12.1814 11.4775 12.2866 11.4567 12.3848 11.416C12.4829 11.3754 12.5723 11.3154 12.6475 11.2402C12.7225 11.1651 12.7817 11.0756 12.8223 10.9775C12.8629 10.8794 12.8838 10.7741 12.8838 10.668V10.6611C12.8837 10.555 12.8629 10.4496 12.8223 10.3516C12.7817 10.2537 12.7223 10.1648 12.6475 10.0898C12.5724 10.0147 12.4829 9.95472 12.3848 9.91406C12.2866 9.87342 12.1814 9.85256 12.0752 9.85254H7.59961Z" fill="#1D6FE9"/> |
| | | </g> |
| | | </g> |
| | | </svg> |
| New file |
| | |
| | | page { |
| | | font-size: $u-font-base; |
| | | color: $u-main-color; |
| | | background-color: $u-bg-color; |
| | | |
| | | height: 100%; |
| | | |
| | | } |
| New file |
| | |
| | | // 主题CSS变量 |
| | | :root, |
| | | page { |
| | | // 主色调 |
| | | --theme-primary: #21d59d; |
| | | --theme-success: #3ed268; |
| | | --theme-warning: #fe9831; |
| | | --theme-error: #fa4e62; |
| | | |
| | | // 文字颜色 |
| | | --theme-main-color: #1b233b; |
| | | --theme-content-color: #60687e; |
| | | --theme-tips-color: #7e869a; |
| | | --theme-light-color: #bdc3d2; |
| | | --theme-disabled-color: #dce0eb; |
| | | |
| | | // 背景颜色 |
| | | --theme-bg-color: #ffffff; |
| | | --theme-bg-color-secondary: #f8f9fa; |
| | | |
| | | // 边框颜色 |
| | | --theme-border-color: #e9ecef; |
| | | } |
| | | |
| | | .theme-dark { |
| | | // 主色调 |
| | | --theme-primary: #3c9cff; |
| | | --theme-success: #5ac725; |
| | | --theme-warning: #f9ae3d; |
| | | --theme-error: #f56c6c; |
| | | |
| | | // 文字颜色 |
| | | --theme-main-color: #ffffff; |
| | | --theme-content-color: #b0b8c1; |
| | | --theme-tips-color: #8a8f95; |
| | | --theme-light-color: #6c757d; |
| | | --theme-disabled-color: #495057; |
| | | |
| | | // 背景颜色 |
| | | --theme-bg-color: #1a1a1a; |
| | | --theme-bg-color-secondary: #2d2d2d; |
| | | } |
| | | |
| | | // 主题工具类 |
| | | .theme-bg { |
| | | background-color: var(--theme-bg-color); |
| | | } |
| | | |
| | | .theme-bg-secondary { |
| | | background-color: var(--theme-bg-color-secondary); |
| | | } |
| | | |
| | | .theme-text { |
| | | color: var(--theme-main-color); |
| | | } |
| | | |
| | | .theme-text-content { |
| | | color: var(--theme-content-color); |
| | | } |
| | | |
| | | .theme-text-tips { |
| | | color: var(--theme-tips-color); |
| | | } |
| New file |
| | |
| | | import { createPinia } from "pinia" |
| | | // pinia 持久化插件 |
| | | import { createPersistedState } from "pinia-plugin-persistedstate" |
| | | |
| | | // 导入子模块 |
| | | import useAppStore from "./modules/app" |
| | | import useUserStore from "./modules/user" |
| | | import useMapStore from "./modules/map" |
| | | |
| | | // 安装pinia状态管理插件 |
| | | function setupStore (app) { |
| | | const store = createPinia() |
| | | |
| | | const piniaPersist = createPersistedState({ |
| | | storage: { |
| | | getItem: uni.getStorageSync, |
| | | setItem: uni.setStorageSync |
| | | } |
| | | }) |
| | | store.use(piniaPersist) |
| | | |
| | | app.use(store) |
| | | } |
| | | |
| | | // 导出模块 |
| | | export { useAppStore, useUserStore, useMapStore } |
| | | export default setupStore |
| New file |
| | |
| | | import { defineStore } from 'pinia' |
| | | import storage from '@/utils/storage' |
| | | |
| | | // 缓存的主题 |
| | | const THEME_KEY = 'app-theme' |
| | | |
| | | const useAppStore = defineStore('app', { |
| | | state: () => ({ |
| | | systemInfo: {}, // 原本 TS: {} as UniApp.GetSystemInfoResult |
| | | theme: storage.get(THEME_KEY) || 'light', |
| | | deviceUpdateKey: 0, //设备刷新key |
| | | jobUpdateKey: 0, //任务刷新key |
| | | }), |
| | | getters: { |
| | | getSystemInfo (state) { |
| | | return state.systemInfo |
| | | }, |
| | | getTheme (state) { |
| | | return state.theme |
| | | } |
| | | }, |
| | | actions: { |
| | | setSystemInfo (info) { |
| | | this.systemInfo = info |
| | | }, |
| | | setDeviceUpdateKeyAdd () { |
| | | console.log(111, this.deviceUpdateKey + 1) |
| | | this.deviceUpdateKey = this.deviceUpdateKey + 1 |
| | | }, |
| | | setJobUpdateKeyAdd (state, data) { |
| | | this.deviceUpdateKey = this.deviceUpdateKey + 1 |
| | | }, |
| | | initSystemInfo () { |
| | | uni.getSystemInfo({ |
| | | success: (res) => { |
| | | this.setSystemInfo(res) |
| | | }, |
| | | fail: (err) => { |
| | | console.error(err) |
| | | } |
| | | }) |
| | | }, |
| | | /** |
| | | * 设置主题 |
| | | */ |
| | | setTheme (theme) { |
| | | this.theme = theme |
| | | // 保存到本地存储 |
| | | storage.set(THEME_KEY, this.theme) |
| | | }, |
| | | checkUpdate () { |
| | | const updateManager = uni.getUpdateManager() |
| | | updateManager.onCheckForUpdate((res) => { |
| | | // 请求完新版本信息的回调 |
| | | console.log(res.hasUpdate) |
| | | }) |
| | | updateManager.onUpdateReady(() => { |
| | | uni.showModal({ |
| | | title: '更新提示', |
| | | content: '新版本已经准备好,是否重启应用?', |
| | | success (res) { |
| | | if (res.confirm) { |
| | | // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 |
| | | updateManager.applyUpdate() |
| | | } |
| | | } |
| | | }) |
| | | }) |
| | | updateManager.onUpdateFailed((res) => { |
| | | console.error(res) |
| | | // 新的版本下载失败 |
| | | uni.showToast({ |
| | | title: '更新失败', |
| | | icon: 'error' |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | export default useAppStore |
| New file |
| | |
| | | import { |
| | | defineStore |
| | | } from 'pinia' |
| | | |
| | | const useMapStore = defineStore('map', { |
| | | state: () => ({ |
| | | selectMapLayerKey: 1 // 默认展示地图 |
| | | }), |
| | | actions: { |
| | | setSelectMapLayerKey(selectMapLayerKey) { |
| | | this.selectMapLayerKey = selectMapLayerKey |
| | | }, |
| | | }, |
| | | |
| | | getters: { |
| | | getSelectMapLayerKey(state) { |
| | | return state.selectMapLayerKey |
| | | }, |
| | | }, |
| | | |
| | | persist: true //持久化 |
| | | }) |
| | | |
| | | export default useMapStore |
| New file |
| | |
| | | import {defineStore} from 'pinia' |
| | | |
| | | const useUserStore = defineStore('user', { |
| | | state: () => ({ |
| | | userInfo: null // 用户信息 |
| | | }), |
| | | actions: { |
| | | setUserInfo(userInfo) { |
| | | this.userInfo = userInfo |
| | | }, |
| | | // 重置 |
| | | resetUserStore() { |
| | | this.$reset() |
| | | }, |
| | | // 合并 |
| | | mergeUserStore(data) { |
| | | this.$patch(data) |
| | | }, |
| | | }, |
| | | persist: true //持久化 |
| | | }) |
| | | |
| | | export default useUserStore |
| New file |
| | |
| | | <!-- |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-16 11:02:27 |
| | | * @FilePath : \src\subPackages\404\index.vue |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | --> |
| | | <template> |
| | | <div class="not-found"> |
| | | <u-navbar left-icon-size="40rpx" @left-click="handleBack" /> |
| | | <u-empty |
| | | mode="page" |
| | | text-size="20" |
| | | text="页面不存在" |
| | | :icon="errorImage" |
| | | width="380" |
| | | height="380" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getAssetsImage } from "@/utils/index.js"; |
| | | import { HOME_PATH } from "@/router"; |
| | | |
| | | const errorImage = getAssetsImage("/images/404.png"); |
| | | |
| | | function handleBack() { |
| | | uni.$u.route({ |
| | | type: "switchTab", |
| | | url: HOME_PATH, |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .not-found { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 100%; |
| | | overflow: auto; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 跳转第三方应用 --> |
| | | <template> |
| | | <view class="content"> |
| | | <!-- WebView组件 --> |
| | | <web-view :src="webViewUrl"></web-view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | webViewUrl: '' // WebView要加载的URL |
| | | }; |
| | | }, |
| | | onLoad(options) { |
| | | // 从导航参数中获取URL |
| | | if (options.url) { |
| | | this.webViewUrl = decodeURIComponent(options.url); |
| | | } else { |
| | | uni.showToast({ |
| | | title: '未获取到URL', |
| | | icon: 'none' |
| | | }); |
| | | // 如果没有URL,可以返回上一页或做其他处理 |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | .content { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <div class="avatarBox"> |
| | | <u-avatar @click="uploadAvatar" :src="userInfo.avatar" size="114" mode="aspectFill" /> |
| | | </div> |
| | | <view class="detailBox"> |
| | | <div class="detailCon"> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">姓名</div> |
| | | <div>{{userInfo.realName}}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">所属单位</div> |
| | | <div>{{userInfo.deptName}}</div> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">手机号</div> |
| | | <u-input input-align="right" v-model="userInfo.phone" type="number" placeholder="请输入手机号" |
| | | class="input-item" /> |
| | | |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">邮箱</div> |
| | | <u-input input-align="right" v-model="userInfo.email" type="email" placeholder="请输入邮箱" |
| | | class="input-item" /> |
| | | </div> |
| | | </div> |
| | | </view> |
| | | <view class="btngroup"> |
| | | <u-button color="#AEAEAE" class="custom-style" shape="circle" @click="reset">重置</u-button> |
| | | <u-button color="#1D6FE9" class="custom-style" shape="circle" @click="submit">提交</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | getEnvObj, |
| | | getWebViewUrl |
| | | } from "@/utils/index.js"; |
| | | import { |
| | | getUserInfo, |
| | | updateInfo, |
| | | updatePassword |
| | | } from '@/api/user/index.js'; |
| | | import { |
| | | useUserStore |
| | | } from "@/store/index.js"; |
| | | const userInfo = ref({ |
| | | id: '', |
| | | avatar: '', |
| | | realName: '', |
| | | name: '', |
| | | phone: '', |
| | | email: '', |
| | | deptName: '', |
| | | }); |
| | | // 校验手机号 |
| | | const validatePhone = () => { |
| | | const phone = userInfo.value.phone |
| | | if (!phone) return true |
| | | const phoneRegex = /^1[3-9]\d{9}$/ |
| | | if (!phoneRegex.test(phone)) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入正确的手机号码', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false |
| | | } |
| | | return true |
| | | } |
| | | // 校验邮箱 |
| | | const validateEmail = () => { |
| | | if (!userInfo.value.email) return true |
| | | const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ |
| | | if (!emailRegex.test(userInfo.value.email)) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入正确的邮箱地址', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false |
| | | } |
| | | return true |
| | | } |
| | | const getUserInfoData = () => { |
| | | getUserInfo().then(res => { |
| | | const user = res.data.data; |
| | | userInfo.value = { |
| | | id: user.id, |
| | | avatar: user.avatar, |
| | | name: user.name, |
| | | realName: user.realName, |
| | | phone: user.phone, |
| | | email: user.email, |
| | | deptName: user.deptName, |
| | | }; |
| | | |
| | | }); |
| | | }; |
| | | const reset = () => { |
| | | getUserInfoData(); |
| | | }; |
| | | |
| | | const { |
| | | VITE_API_BASE_URL |
| | | } = getEnvObj() |
| | | |
| | | function uploadUtil(options) { |
| | | const { |
| | | formData, |
| | | filePath, |
| | | url |
| | | } = options; |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | let accessToken = useUserStore()?.$state?.userInfo?.access_token; |
| | | |
| | | uni.uploadFile({ |
| | | url: `${VITE_API_BASE_URL}${url}`, |
| | | name: 'file', |
| | | header: { |
| | | 'Blade-Auth': 'bearer ' + accessToken |
| | | }, |
| | | filePath: filePath, |
| | | formData, |
| | | success: (res) => { |
| | | const resData = JSON.parse(res.data) |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | resolve(res) |
| | | } else { |
| | | showToast(resData.message) |
| | | |
| | | reject(res) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | reject(err) |
| | | } |
| | | }); |
| | | }) |
| | | } |
| | | const uploadAvatar = () => { |
| | | uni.chooseImage({ |
| | | count: 1, |
| | | success: (res) => { |
| | | const tempFile = res.tempFiles[0]; // 获取文件对象 |
| | | const filePath = tempFile.path || tempFile.tempFilePath; |
| | | if (!filePath) { |
| | | uni.showToast({ |
| | | title: '获取文件路径失败', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | let fileName = tempFile.name; |
| | | if (!fileName) { |
| | | const pathWithoutProtocol = filePath.replace(/^file:\/\//, ''); |
| | | fileName = pathWithoutProtocol.split('/').pop() || 'unknown.png'; |
| | | } |
| | | |
| | | // 显示加载中 |
| | | uni.showLoading({ |
| | | title: '上传中...' |
| | | }); |
| | | |
| | | // 上传文件 |
| | | uploadUtil({ |
| | | filePath: filePath, |
| | | formData: { |
| | | fileName: fileName, |
| | | sn: 'avatar_upload' |
| | | }, |
| | | url: '/blade-resource/oss/endpoint/put-file' |
| | | }).then(res => { |
| | | const resData = JSON.parse(res.data); |
| | | if (resData.code === 200 || resData.code === 0) { |
| | | // 更新头像显示 |
| | | userInfo.value.avatar = resData.data.link || resData.data.url; |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: '头像上传成功', |
| | | icon: 'success' |
| | | }); |
| | | } else { |
| | | throw new Error(resData.message || '上传失败'); |
| | | |
| | | } |
| | | }).catch(err => { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: err.message || '上传失败', |
| | | icon: 'none' |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | const submit = () => { |
| | | if (!validatePhone() || !validateEmail()) return |
| | | userInfo.value.name = userInfo.value.realName; |
| | | updateInfo(userInfo.value).then(res => { |
| | | if (res.data.code === 200) { |
| | | uni.showToast({ |
| | | title: '修改信息成功', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | getUserInfoData() |
| | | |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg, |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | getUserInfoData() |
| | | } |
| | | |
| | | }); |
| | | |
| | | }; |
| | | onShow(async () => { |
| | | getUserInfoData() |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | .avatarBox { |
| | | width: 228rpx; |
| | | height: 228rpx; |
| | | margin: 76rpx 0; |
| | | } |
| | | |
| | | .detailBox { |
| | | width: 702rpx; |
| | | min-height: 430rpx; |
| | | background: #FFFFFF; |
| | | border-radius: 12rpx; |
| | | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | .detailCon { |
| | | padding: 0 24rpx; |
| | | } |
| | | |
| | | .orderRow { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 96rpx; |
| | | border-bottom: 2rpx solid #f5f5f5; |
| | | color: #7b7b7b; |
| | | |
| | | .rowTitle { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | ::v-deep .u-input { |
| | | border: none !important; |
| | | background: transparent !important; |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | ::v-deep .u-input__input { |
| | | border: none !important; |
| | | box-shadow: none !important; |
| | | background: transparent !important; |
| | | padding: 0 !important; |
| | | margin: 0 !important; |
| | | height: auto !important; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .btngroup { |
| | | display: flex; |
| | | position: absolute; |
| | | bottom: 150rpx; |
| | | } |
| | | |
| | | :deep(.u-button:first-child) { |
| | | margin-right: 30rpx !important; |
| | | } |
| | | |
| | | .custom-style { |
| | | width: 276rpx; |
| | | height: 76rpx; |
| | | } |
| | | :deep(.u-button.data-v-461e713c){ |
| | | width: 276rpx !important; |
| | | height: 76rpx !important; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- 修改密码 --> |
| | | <template> |
| | | <view class="container"> |
| | | <view class="detailBox"> |
| | | <div class="detailCon"> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">原始密码</div> |
| | | <input type="password" v-model="passwordForm.oldPassword" placeholder="请输入" class="input-item" /> |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">新密码</div> |
| | | <input type="password" v-model="passwordForm.newPassword" placeholder="请输入" class="input-item" /> |
| | | |
| | | </div> |
| | | <div class="orderRow"> |
| | | <div class="rowTitle">确认密码</div> |
| | | <input type="password" v-model="passwordForm.newPassword1" placeholder="请输入" class="input-item" /> |
| | | </div> |
| | | </div> |
| | | </view> |
| | | <view class="btngroup"> |
| | | <u-button color="#AEAEAE" class="custom-style" shape="circle" @click="reset">重置</u-button> |
| | | <u-button color="#1D6FE9" class="custom-style" shape="circle" @click="submit">提交</u-button> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | useUserStore |
| | | } from "@/store/index.js"; |
| | | import md5 from "js-md5"; |
| | | import { |
| | | getUserInfo, |
| | | updateInfo, |
| | | updatePassword |
| | | } from '@/api/user/index.js'; |
| | | const passwordIcon = { |
| | | show: 'fas fa-eye', // 显示密码时的图标 |
| | | hide: 'fas fa-eye-slash' // 隐藏密码时的图标 |
| | | } |
| | | const userStore = useUserStore(); |
| | | const passwordForm = ref({ |
| | | oldPassword: '', |
| | | newPassword: '', |
| | | newPassword1: '', |
| | | }); |
| | | // 校验密码不能包含中文 |
| | | const validatePasswordNoChinese = (password) => { |
| | | const chineseRegex = /[\u4e00-\u9fa5]/; |
| | | if (chineseRegex.test(password)) { |
| | | |
| | | uni.showToast({ |
| | | title: '密码不能包含中文字符', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false; |
| | | } |
| | | return true; |
| | | }; |
| | | // 校验密码复杂度(长度≥6位,包含字母和数字) |
| | | const validatePasswordStrength = (password) => { |
| | | if (password.length < 6) { |
| | | |
| | | uni.showToast({ |
| | | title: '密码长度不能少于6位', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return false; |
| | | } |
| | | // const hasLetter = /[a-zA-Z]/.test(password); |
| | | // const hasNumber = /\d/.test(password); |
| | | // if (!hasLetter || !hasNumber) { |
| | | // ElMessage.error('密码需同时包含字母和数字'); |
| | | // return false; |
| | | // } |
| | | return true; |
| | | }; |
| | | const clearForm = () => { |
| | | passwordForm.value = { |
| | | oldPassword: '', |
| | | newPassword: '', |
| | | newPassword1: '', |
| | | }; |
| | | }; |
| | | const reset = () => { |
| | | clearForm(); |
| | | }; |
| | | const submit = () => { |
| | | // 原始密码校验 |
| | | if (!passwordForm.value.oldPassword) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入原始密码', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | // 中文校验 |
| | | if (!validatePasswordNoChinese(passwordForm.value.newPassword)) return; |
| | | // 新密码校验 |
| | | if (!passwordForm.value.newPassword) { |
| | | |
| | | uni.showToast({ |
| | | title: '请输入新密码', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | // 确认密码校验 |
| | | if (passwordForm.value.newPassword !== passwordForm.value.newPassword1) { |
| | | |
| | | uni.showToast({ |
| | | title: '两次输入的新密码不一致', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 复杂度校验 |
| | | if (!validatePasswordStrength(passwordForm.value.newPassword)) return; |
| | | updatePassword(md5(passwordForm.value.oldPassword), |
| | | md5(passwordForm.value.newPassword), |
| | | md5(passwordForm.value.newPassword1)).then(res => { |
| | | if (res.data.code === 200) { |
| | | uni.showToast({ |
| | | title: '修改信息成功', |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | clearForm(); |
| | | userStore.setUserInfo(null) |
| | | uni.removeStorageSync('rememberedUser'); |
| | | uni.reLaunch({ |
| | | url: '/pages/login/index' |
| | | }) |
| | | |
| | | } else { |
| | | uni.showToast({ |
| | | title: res.msg, |
| | | icon: 'none', |
| | | duration: 2000 |
| | | }); |
| | | } |
| | | |
| | | }); |
| | | |
| | | }; |
| | | onShow(async () => { |
| | | clearForm(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .detailBox { |
| | | margin-top: 40rpx; |
| | | width: 702rpx; |
| | | |
| | | min-height: 326rpx; |
| | | background: #FFFFFF; |
| | | border-radius: 12rpx; |
| | | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | .detailCon { |
| | | padding: 0 24rpx; |
| | | } |
| | | |
| | | .orderRow { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | height: 96rpx; |
| | | border-bottom: 2rpx solid #f5f5f5; |
| | | color: #7b7b7b; |
| | | |
| | | |
| | | .rowTitle { |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: 400; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | input.input-item { |
| | | text-align: right; |
| | | border: none !important; |
| | | background: transparent !important; |
| | | box-shadow: none !important; |
| | | padding: 0 !important; |
| | | margin: 0 !important; |
| | | height: auto !important; |
| | | |
| | | outline: none; |
| | | font-size: 30rpx; |
| | | color: #222324; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | } |
| | | :deep(.uni-input-placeholder) { |
| | | color: #D5D5D5; |
| | | } |
| | | input.input-item::placeholder { |
| | | font-size: 30rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .btngroup { |
| | | display: flex; |
| | | position: absolute; |
| | | bottom: 150rpx; |
| | | } |
| | | |
| | | :deep(.u-button:first-child) { |
| | | margin-right: 30rpx !important; |
| | | } |
| | | |
| | | .custom-style { |
| | | width: 276rpx; |
| | | height: 76rpx; |
| | | } |
| | | :deep(.u-button.data-v-461e713c){ |
| | | width: 276rpx !important; |
| | | height: 76rpx !important; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- |
| | | * @Author : yuan |
| | | * @Date : 2025-11-13 18:14:52 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-20 16:56:27 |
| | | * @FilePath : \src\subPackages\workDetail\addWork\index.vue |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-11-13 18:14:52 |
| | | --> |
| | | <template> |
| | | <view> |
| | | <WebViewPlus |
| | | @webMessage="onPostMessage" |
| | | ref="sWebViewRef" |
| | | :src="`${viewUrl}`" |
| | | /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getWebViewUrl } from "@/utils/index.js"; |
| | | import WebViewPlus from "@/components/WebViewPlus.vue"; |
| | | const sWebViewRef = ref(null); |
| | | const viewUrl = getWebViewUrl("/addWork"); |
| | | |
| | | function onPostMessage(data) { |
| | | if (data.type === "submitSuccess") { |
| | | // #ifdef MP-WEIXIN |
| | | if ("fun" in data && data.fun === "add") { |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | } |
| | | // #endif |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | // uni.switchTab({ |
| | | // url: '/pages/work/index' |
| | | // }); |
| | | uni.switchTab({ |
| | | url: `/pages/work/index?addLog=111`, |
| | | }); |
| | | // #endif |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| New file |
| | |
| | | <!-- 工单详情 - 包含待审核、待处理、处理中、已完成 --> |
| | | <template> |
| | | <div class="workDetailContainer"> |
| | | <WebViewPlus |
| | | ref="sWebViewRef" |
| | | :src="`${viewUrl}`" |
| | | @webMessage="onPostMessage" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getWebViewUrl } from "@/utils/index.js"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | import { useUserStore } from "@/store/index.js"; |
| | | const userStore = useUserStore(); |
| | | const userInfo = userStore.userInfo; |
| | | const sWebViewRef = ref(null); |
| | | const viewUrl = ref(""); |
| | | onLoad((options) => { |
| | | const eventNum = options.eventNum; |
| | | viewUrl.value = getWebViewUrl("/workDetail", { |
| | | eventNum: eventNum, |
| | | totalNum: options.totalNum, |
| | | keyword: options.keyword, |
| | | aiType: options.aiType, |
| | | wLJobInfoId: options.wLJobInfoId, |
| | | status: options.status, |
| | | current: options.current, |
| | | }); |
| | | }); |
| | | |
| | | function onPostMessage(data) { |
| | | if (data.type === "workback") { |
| | | // #ifdef MP-WEIXIN |
| | | if ("fun" in data && data.fun === "add") { |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | } |
| | | // #endif |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | uni.setStorageSync("joinParams", { |
| | | type: "add", |
| | | }); |
| | | uni.switchTab({ |
| | | url: `/pages/work/index?addLog=111`, |
| | | // url: '/pages/work/index' |
| | | }); |
| | | // #endif |
| | | } else if (data.type === "jumpMapNav") { |
| | | // #ifndef MP-WEIXIN |
| | | uni.navigateTo({ |
| | | url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`, |
| | | }); |
| | | // #endif |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .workDetailContainer { |
| | | width: 100%; |
| | | height: 100%; |
| | | background-size: cover; |
| | | } |
| | | </style> |
| New file |
| | |
| | | <!-- |
| | | * @Author : yuan |
| | | * @Date : 2025-10-22 14:59:10 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-19 14:52:54 |
| | | * @FilePath : \src\subPackages\workDetail\mapWork\index.vue |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-10-22 14:59:10 |
| | | --> |
| | | <!-- 地图展示 --> |
| | | <template> |
| | | <WebViewPlus |
| | | ref="sWebViewRef" |
| | | :src="`${viewUrl}`" |
| | | @webMessage="onPostMessage" |
| | | /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getWebViewUrl } from "@/utils/index.js"; |
| | | import { onLoad } from "@dcloudio/uni-app"; |
| | | |
| | | const sWebViewRef = ref(null); |
| | | const viewUrl = ref(""); |
| | | |
| | | onLoad((options) => { |
| | | const currentItem = options.currentItem; |
| | | viewUrl.value = getWebViewUrl("/mapWork", { currentItem: currentItem }); |
| | | }); |
| | | function onPostMessage(data) { |
| | | // #ifdef MP-WEIXIN |
| | | // #endif |
| | | |
| | | // #ifndef MP-WEIXIN |
| | | if (data.type === "workDetailback") { |
| | | // uni.navigateTo({ |
| | | // url: '/subPackages/workDetail/index' |
| | | // }); |
| | | uni.navigateBack({ |
| | | delta: 1, |
| | | }); |
| | | } |
| | | |
| | | if (data.type === "browser") { |
| | | uni.navigateTo({ |
| | | url: |
| | | "/subPackages/browser/index?url=" + encodeURIComponent(data.data.url), |
| | | }); |
| | | } |
| | | // #endif |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| New file |
| | |
| | | |
| | | <!-- 照片放大 --> |
| | | <template> |
| | | <view> |
| | | <WebViewPlus v-if="isApp" ref="sWebViewRef" :src="`${viewUrl}`" @webMessage="onPostMessage"/></view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {getWebViewUrl} from "@/utils/index.js"; |
| | | import { onLoad } from '@dcloudio/uni-app'; |
| | | const viewUrl = ref('') |
| | | onLoad( (options) => { |
| | | const eventNum= options.eventNum; |
| | | viewUrl.value = getWebViewUrl('/photoMagnify', {eventNum:eventNum}) |
| | | }); |
| | | const isApp = ref(false) |
| | | onShow(() => { |
| | | isApp.value = true |
| | | }); |
| | | |
| | | onHide(() => { |
| | | isApp.value = false |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| New file |
| | |
| | | @import 'uview-plus/theme.scss'; |
| | | @import '@/static/styles/theme.scss'; |
| | | |
| | | /* 颜色变量 - 使用CSS变量支持主题切换 */ |
| | | |
| | | /* 行为相关颜色 */ |
| | | $u-primary: var(--theme-primary); |
| | | $u-primary-dark: var(--theme-primary-dark); |
| | | $u-success: var(--theme-success); |
| | | $u-warning: var(--theme-warning); |
| | | $u-error: var(--theme-error); |
| | | |
| | | /* 文字基本颜色 */ |
| | | $u-main-color: var(--theme-main-color); |
| | | $u-content-color: var(--theme-content-color); |
| | | $u-tips-color: var(--theme-tips-color); |
| | | $u-light-color: var(--theme-light-color); |
| | | $u-disabled-color: var(--theme-disabled-color); |
| | | |
| | | /* 背景颜色 */ |
| | | $u-bg-color: var(--theme-bg-color); |
| | | |
| | | /* 边框颜色 */ |
| | | $u-border-color: var(--theme-border-color); |
| | | |
| | | /* 尺寸变量 */ |
| | | |
| | | /* 文字尺寸 */ |
| | | $u-font-sm: 24rpx; |
| | | $u-font-base: 28rpx; |
| | | $u-font-lg: 32rpx; |
| | | |
| | | /* 图片尺寸 */ |
| | | $u-img-sm: 40rpx; |
| | | $u-img-base: 52rpx; |
| | | $u-img-lg: 80rpx; |
| | | |
| | | /* Border Radius */ |
| | | $u-border-radius-sm: 4rpx; |
| | | $u-border-radius-base: 6rpx; |
| | | $u-border-radius-lg: 12rpx; |
| | | $u-border-radius-circle: 50%; |
| | | |
| | | /* 水平间距 */ |
| | | $u-spacing-row-sm: 10rpx; |
| | | $u-spacing-row-base: 20rpx; |
| | | $u-spacing-row-lg: 30rpx; |
| | | |
| | | /* 垂直间距 */ |
| | | $u-spacing-col-sm: 8rpx; |
| | | $u-spacing-col-base: 16rpx; |
| | | $u-spacing-col-lg: 24px; |
| | | |
| | | /* 透明度 */ |
| | | $u-opacity-disabled: 0.3; |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-10-15 15:52:12 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-12-17 14:09:14 |
| | | * @FilePath : \src\utils\common\index.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-10-15 15:52:12 |
| | | */ |
| | | // 小程序更新检测 |
| | | import { useUserStore } from "@/store/index.js" |
| | | import configEnv from "@/config/env.js" |
| | | import process from "node:process" |
| | | |
| | | export function mpUpdate () { |
| | | const updateManager = uni.getUpdateManager() |
| | | updateManager.onCheckForUpdate(res => { |
| | | // 请求完新版本信息的回调 |
| | | console.log(res.hasUpdate) |
| | | }) |
| | | updateManager.onUpdateReady(() => { |
| | | uni.showModal({ |
| | | title: "更新提示", |
| | | content: "检测到新版本,是否下载新版本并重启小程序?", |
| | | success (res) { |
| | | if (res.confirm) { |
| | | // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启 |
| | | updateManager.applyUpdate() |
| | | } |
| | | } |
| | | }) |
| | | }) |
| | | updateManager.onUpdateFailed(() => { |
| | | // 新的版本下载失败 |
| | | uni.showModal({ |
| | | title: "已经有新版本了哟~", |
| | | content: "新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~", |
| | | showCancel: false |
| | | }) |
| | | }) |
| | | } |
| | | export function getStatusBarHeight () { |
| | | try { |
| | | const systemInfo = uni.getWindowInfo() |
| | | |
| | | // #ifdef APP-PLUS |
| | | return systemInfo.statusBarHeight || 0 |
| | | // #endif |
| | | |
| | | // #ifdef MP-WEIXIN |
| | | return 0 |
| | | // #endif |
| | | |
| | | // #ifdef H5 |
| | | return systemInfo.statusBarHeight || 0 |
| | | // #endif |
| | | return systemInfo.statusBarHeight || 0 |
| | | } catch (error) { |
| | | return 0 |
| | | } |
| | | } |
| | | export function getEnvObj () { |
| | | return configEnv[__APP_ENV__?.ENV_NAME] || {} |
| | | } |
| | | |
| | | export function getWebViewUrl (targetUrl, otherParams) { |
| | | const userStore = useUserStore() |
| | | const url = getEnvObj().VITE_APP_WEBVIEW_URL |
| | | const uniPlatform = __APP_ENV__.UNI_PLATFORM |
| | | const statusBarHeight = getStatusBarHeight() |
| | | // 1. 处理用户参数 |
| | | const userParams = userStore?.userInfo ? JSON.stringify(userStore.userInfo) : '{}' |
| | | // 2. 构建查询参数字符串 |
| | | let queryString = `params=${encodeURIComponent(userParams)}&topMargin=${statusBarHeight}&uniPlatform=${uniPlatform}` |
| | | |
| | | // 3. 处理 otherParams 对象 |
| | | if (otherParams && typeof otherParams === 'object') { |
| | | Object.keys(otherParams).forEach(key => { |
| | | const value = otherParams[key] |
| | | if (value !== undefined && value !== null) { |
| | | queryString += `&${key}=${encodeURIComponent(value)}` |
| | | } |
| | | }) |
| | | } |
| | | // 4. 拼接完整 URL |
| | | return `${url}${targetUrl}?${queryString}` |
| | | } |
| | | |
| | | export function getAssetsImage (targetUrl) { |
| | | const url = getEnvObj().VITE_APP_ASSETS_URL |
| | | return `${url}${targetUrl}` |
| | | } |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 10:07:13 |
| | | * @FilePath : \src\utils\index.ts |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | export * from "./common" |
| | | export * from "./modals" |
| | | export * from "./request" |
| | | export * from "./storage" |
| New file |
| | |
| | | /** |
| | | * 轻提示 |
| | | * @param {string} content 提示内容 |
| | | * @param {object} option 配置 |
| | | */ |
| | | export function Toast (content, option = {}) { |
| | | uni.showToast({ |
| | | title: content, |
| | | icon: "none", |
| | | mask: true, |
| | | duration: 1500, |
| | | ...option |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * Loading 提示框 |
| | | * @param {string} content 提示内容 |
| | | */ |
| | | export const Loading = { |
| | | show: (content = "加载中") => { |
| | | uni.showLoading({ |
| | | title: content, |
| | | mask: true |
| | | }) |
| | | }, |
| | | hide: () => { |
| | | uni.hideLoading() |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Dialog 提示框 |
| | | * @param {string} content 提示内容 |
| | | * @param {object} option 配置 |
| | | */ |
| | | export function Dialog (content, option = {}) { |
| | | option.showCancel = false |
| | | return new Promise((resolve, reject) => { |
| | | uni.showModal({ |
| | | title: "温馨提示", |
| | | content, |
| | | showCancel: false, |
| | | confirmColor: "#1677FF", |
| | | success (res) { |
| | | if (res.confirm) resolve(res) |
| | | }, |
| | | fail () { |
| | | reject(new Error("Alert 调用失败 !")) |
| | | }, |
| | | ...option |
| | | }) |
| | | }) |
| | | } |
| New file |
| | |
| | | import Request from "uview-plus/libs/luch-request/index" |
| | | import { requestInterceptors, responseInterceptors } from "./interceptors" |
| | | import configEnv from "@/config/env.js"; |
| | | import {getEnvObj} from "@/utils/index.js"; |
| | | |
| | | const http = new Request() |
| | | |
| | | export function request (config) { |
| | | return new Promise((resolve, reject) => { |
| | | http |
| | | .request(config) |
| | | .then(res => { |
| | | resolve(res) |
| | | }) |
| | | .catch(err => { |
| | | reject(err) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 引入拦截器配置 |
| | | export function setupRequest () { |
| | | http.setConfig(defaultConfig => { |
| | | /* defaultConfig 为默认全局配置 */ |
| | | defaultConfig.baseURL = getEnvObj().VITE_API_BASE_URL |
| | | // #ifdef H5 |
| | | if (import.meta.env.VITE_APP_PROXY === "true") { |
| | | defaultConfig.baseURL = import.meta.env.VITE_API_PREFIX |
| | | } |
| | | // #endif |
| | | return defaultConfig |
| | | }) |
| | | requestInterceptors(http) |
| | | responseInterceptors(http) |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | export function get (url, config) { |
| | | return request({ ...config, url, method: "GET" }) |
| | | } |
| | | |
| | | export function post (url, config) { |
| | | return request({ ...config, url, method: "POST" }) |
| | | } |
| | | |
| | | export function upload (url, config) { |
| | | return request({ ...config, url, method: "UPLOAD" }) |
| | | } |
| | | |
| | | export function download (url, config) { |
| | | return request({ ...config, url, method: "DOWNLOAD" }) |
| | | } |
| | | |
| | | export default setupRequest |
| New file |
| | |
| | | import { |
| | | useUserStore |
| | | } from "@/store" |
| | | import storage from "@/utils/storage" |
| | | import { |
| | | showMessage |
| | | } from "./status" |
| | | import website from '@/config/website' |
| | | import { |
| | | Base64 |
| | | } from 'js-base64' |
| | | |
| | | // 防止重复提交 |
| | | const repeatSubmit = config => { |
| | | const requestObj = { |
| | | url: config.url, |
| | | data: typeof config.data === "object" ? |
| | | JSON.stringify(config.data) : config.data, |
| | | time: new Date().getTime() |
| | | } |
| | | const sessionObj = storage.getJSON("sessionObj") |
| | | if (!sessionObj) { |
| | | storage.setJSON("sessionObj", requestObj) |
| | | } else { |
| | | const s_url = sessionObj.url // 请求地址 |
| | | const s_data = sessionObj.data // 请求数据 |
| | | const s_time = sessionObj.time // 请求时间 |
| | | const interval = 1000 // 间隔时间(ms),小于此时间视为重复提交 |
| | | if ( |
| | | s_data === requestObj.data && |
| | | requestObj.time - s_time < interval && |
| | | s_url === requestObj.url |
| | | ) { |
| | | const message = "数据正在处理,请勿重复提交" |
| | | console.warn(`[${s_url}]: ${message}`) |
| | | return Promise.reject(new Error(message)) |
| | | } else { |
| | | storage.setJSON("sessionObj", requestObj) |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 请求拦截器 |
| | | function requestInterceptors(http) { |
| | | |
| | | http.interceptors.request.use((config) => { |
| | | const {detail} = useUserStore().$state?.userInfo || {} |
| | | // 假设有token值需要在头部需要携带 |
| | | let accessToken = useUserStore()?.$state?.userInfo?.access_token; |
| | | if (accessToken) { |
| | | config.header['Blade-Auth'] = 'bearer ' + accessToken; |
| | | } |
| | | if (detail?.areaCode) { |
| | | config.header['areaCode'] = detail.areaCode |
| | | } |
| | | // 安全请求header |
| | | config.header['Blade-Requested-With'] = 'BladeHttpRequest'; |
| | | // 客户端认证参数 |
| | | config.header['Authorization'] = 'Basic ' + Base64.encode(website.clientId + ':' + website.clientSecret); |
| | | return config |
| | | }, config => { // 可使用async await 做异步操作 |
| | | return Promise.reject(config) |
| | | }) |
| | | } |
| | | |
| | | // 响应拦截器 |
| | | function responseInterceptors(http) { |
| | | http.interceptors.response.use((response) => { |
| | | let res = response |
| | | const status = res.data.error_code || res.data.code || res.statusCode |
| | | const message = res?.data?.msg || res?.data?.error_description || res?.data?.message || '系统错误' |
| | | if (status !== 200) { |
| | | uni.showToast({title: message, icon: 'none'}); |
| | | return Promise.reject(response); |
| | | } |
| | | return response; |
| | | }, (response) => { |
| | | let res = response |
| | | const message = res?.data?.msg || res?.data?.error_description || res?.data?.message || '系统错误' |
| | | /* 对响应错误做点什么 (statusCode !== 200)*/ |
| | | uni.showToast({title: message, icon: 'none'}); |
| | | if (response.statusCode === 401) { |
| | | const pages = getCurrentPages() |
| | | const currentPage = pages[pages.length - 1] |
| | | uni.reLaunch({ |
| | | url: `/pages/login/index?redirect=/${currentPage.route}` |
| | | }) |
| | | } |
| | | return Promise.reject(response) |
| | | }) |
| | | } |
| | | |
| | | export { |
| | | requestInterceptors, |
| | | responseInterceptors |
| | | } |
| New file |
| | |
| | | /** |
| | | * 根据状态码,生成对应的错误信息 |
| | | * @param {number|string} status 状态码 |
| | | * @returns {string} 错误信息 |
| | | */ |
| | | export const showMessage = status => { |
| | | let message = "" |
| | | switch (status) { |
| | | case 400: |
| | | message = "请求错误(400)" |
| | | break |
| | | case 401: |
| | | message = "未授权,请重新登录(401)" |
| | | break |
| | | case 403: |
| | | message = "拒绝访问(403)" |
| | | break |
| | | case 404: |
| | | message = "请求出错(404)" |
| | | break |
| | | case 408: |
| | | message = "请求超时(408)" |
| | | break |
| | | case 500: |
| | | message = "服务器错误(500)" |
| | | break |
| | | case 501: |
| | | message = "服务未实现(501)" |
| | | break |
| | | case 502: |
| | | message = "网络错误(502)" |
| | | break |
| | | case 503: |
| | | message = "服务不可用(503)" |
| | | break |
| | | case 504: |
| | | message = "网络超时(504)" |
| | | break |
| | | case 505: |
| | | message = "HTTP版本不受支持(505)" |
| | | break |
| | | default: |
| | | message = `连接出错(${status})!` |
| | | } |
| | | return `${message},请检查网络或联系管理员!` |
| | | } |
| New file |
| | |
| | | const storage = { |
| | | set (key, value) { |
| | | if (key !== null && value !== null) uni.setStorageSync(key, value) |
| | | }, |
| | | get (key) { |
| | | if (key === null) return null |
| | | |
| | | return uni.getStorageSync(key) |
| | | }, |
| | | setJSON (key, jsonValue) { |
| | | if (jsonValue !== null) this.set(key, JSON.stringify(jsonValue)) |
| | | }, |
| | | getJSON (key) { |
| | | const value = this.get(key) |
| | | if (value) return JSON.parse(value) |
| | | }, |
| | | remove (key) { |
| | | uni.removeStorageSync(key) |
| | | } |
| | | } |
| | | |
| | | export default storage |
| New file |
| | |
| | | import LibGenerateTestUserSig from './lib-generate-test-usersig-es.min.js'; |
| | | |
| | | const SDKAPPID = 1600112974; |
| | | const SECRETKEY = '45606bc613e715efb9ec9117fed1fef29411630018c65de7f7d3a5290e9c3b83'; |
| | | const EXPIRETIME = 604800; |
| | | |
| | | export function genTestUserSig(userID) { |
| | | const generator = new LibGenerateTestUserSig(SDKAPPID, SECRETKEY, EXPIRETIME); |
| | | const userSig = generator.genTestUserSig(userID); |
| | | |
| | | return { |
| | | SDKAppID: SDKAPPID, |
| | | SECRETKEY, |
| | | userSig, |
| | | }; |
| | | } |
| New file |
| | |
| | | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { |
| | | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } |
| | | return new (P || (P = Promise))(function (resolve, reject) { |
| | | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } |
| | | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } |
| | | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } |
| | | step((generator = generator.apply(thisArg, _arguments || [])).next()); |
| | | }); |
| | | }; |
| | | import { NAME } from './constants.js'; |
| | | import { TRTCRoleType, TRTCAudioQuality, TRTCVideoRotation, TRTCVideoFillMode, TRTCVideoMirrorType, TRTCVideoStreamType, TRTCAppScene, TRTCAudioRoute, TRTCBeautyStyle, } from './TrtcDefines.js'; |
| | | import TrtcError, { TXLiteJSError, generateError_ } from './TrtcCode.js'; |
| | | const TrtcNativeTrtcCloudModule = uni.requireNativePlugin('TRTCCloudUniPlugin-TRTCCloudImpl'); |
| | | const TXAudioEffectManagerModule = uni.requireNativePlugin('TRTCCloudUniPlugin-TRTCCloudImpl-TXAudioEffectManagerModule'); |
| | | const TrtcEvent = uni.requireNativePlugin('globalEvent'); |
| | | let trtcCloud = null; // trtcCloud 单例 |
| | | export default class TrtcCloudImpl { |
| | | constructor() { |
| | | this.listenersMap_ = new Map(); |
| | | } |
| | | static _createInstance() { |
| | | try { |
| | | if (trtcCloud) { |
| | | return trtcCloud; |
| | | } |
| | | TrtcNativeTrtcCloudModule.sharedInstance(); |
| | | trtcCloud = new TrtcCloudImpl(); |
| | | return trtcCloud; |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | static _getInstance() { |
| | | if (trtcCloud) { |
| | | return trtcCloud; |
| | | } |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_OPERATION, |
| | | message: 'get trtcCloud failed, please create trtcCloud first', |
| | | }); |
| | | } |
| | | static _destroyInstance() { |
| | | try { |
| | | trtcCloud = null; |
| | | TrtcNativeTrtcCloudModule.destroySharedInstance(); |
| | | } |
| | | catch (error) { |
| | | throw new TrtcError({ |
| | | code: error.code || TXLiteJSError.UNKNOWN, |
| | | message: error.message, |
| | | name: error.name, |
| | | }); |
| | | } |
| | | } |
| | | // 截图保存 |
| | | // async saveImage_(base64Data) { |
| | | // return new Promise((resolve, reject) => { |
| | | // let bitmap = new plus.nativeObj.Bitmap(); |
| | | // bitmap.loadBase64Data(base64Data, () => { |
| | | // const url = "_doc/" + new Date().getTime() + ".png"; // url为时间戳命名方式 |
| | | // console.log('saveHeadImgFile', url); |
| | | // bitmap.save(url, { overwrite: true }, (i) => { |
| | | // uni.saveImageToPhotosAlbum({ |
| | | // filePath: url, |
| | | // success: function() { |
| | | // uni.showToast({ |
| | | // title: '图片保存成功', |
| | | // icon: 'none' |
| | | // }) |
| | | // bitmap.clear(); |
| | | // resolve({ code: 0, message: '图片保存成功' }); |
| | | // } |
| | | // }); |
| | | // }, (e) => { |
| | | // uni.showToast({ |
| | | // title: '图片保存失败, 请重新截图', |
| | | // icon: 'none' |
| | | // }) |
| | | // bitmap.clear(); |
| | | // resolve({ code: -1, message: '图片保存失败, 请重新截图' }); |
| | | // }); |
| | | // }); |
| | | // }); |
| | | // } |
| | | on(event, callback) { |
| | | if (typeof event !== NAME.STRING || typeof callback !== NAME.FUNCTION) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the on method parameter types. event type is a ${typeof event}; callback type is a ${typeof callback}`, |
| | | }); |
| | | } |
| | | const nativeListener = (res) => __awaiter(this, void 0, void 0, function* () { |
| | | const { data = [] } = res; |
| | | const code = data[0]; |
| | | const message = data[1]; |
| | | const extraInfo = data[2]; |
| | | switch (event) { |
| | | case 'onEnterRoom': { |
| | | const result = code; |
| | | callback(result); |
| | | break; |
| | | } |
| | | case 'onExitRoom': { |
| | | const reason = code; |
| | | callback(reason); |
| | | break; |
| | | } |
| | | case 'onFirstVideoFrame': { |
| | | const userId = code; |
| | | const streamType = data[1]; |
| | | const width = data[2]; |
| | | const height = data[3]; |
| | | callback({ userId, streamType, width, height }); |
| | | break; |
| | | } |
| | | case 'onFirstAudioFrame': { |
| | | const userId = code; |
| | | callback(userId); |
| | | break; |
| | | } |
| | | case 'onMicDidReady': { |
| | | callback(); |
| | | break; |
| | | } |
| | | case 'onCameraDidReady': { |
| | | callback(); |
| | | break; |
| | | } |
| | | case 'onNetworkQuality': { |
| | | const localQuality = data[0]; |
| | | const remoteQuality = data[1]; |
| | | callback({ localQuality, remoteQuality }); |
| | | break; |
| | | } |
| | | case 'onRemoteUserEnterRoom': { |
| | | const userId = code; |
| | | callback(userId); |
| | | break; |
| | | } |
| | | case 'onRemoteUserLeaveRoom': { |
| | | const userId = code; |
| | | const reason = message; |
| | | callback({ userId, reason }); |
| | | break; |
| | | } |
| | | case 'onSendFirstLocalAudioFrame': { |
| | | callback(); |
| | | break; |
| | | } |
| | | case 'onSendFirstLocalVideoFrame': { |
| | | const streamType = code; |
| | | callback(streamType); |
| | | break; |
| | | } |
| | | case 'onStatistics': { |
| | | const statics = data[0]; |
| | | callback(statics); |
| | | break; |
| | | } |
| | | case 'onUserAudioAvailable': { |
| | | const userId = code; |
| | | const available = message; |
| | | callback({ userId, available }); |
| | | break; |
| | | } |
| | | case 'onUserVideoAvailable': { |
| | | const userId = code; |
| | | const available = message; |
| | | callback({ userId, available }); |
| | | break; |
| | | } |
| | | case 'onUserVoiceVolume': { |
| | | const userVolumes = data[0]; |
| | | const totalVolume = data[1]; |
| | | callback({ userVolumes, totalVolume }); |
| | | break; |
| | | } |
| | | case 'onSwitchRole': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onScreenCaptureStarted': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onScreenCapturePaused': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onScreenCaptureResumed': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onScreenCaptureStopped': { |
| | | callback({ code, message }); |
| | | break; |
| | | } |
| | | case 'onUserSubStreamAvailable': { |
| | | const userId = code; |
| | | const available = message; |
| | | callback({ userId, available }); |
| | | break; |
| | | } |
| | | case 'onSnapshotComplete': { |
| | | // base64 直接保存到本地图库 |
| | | // const { code: snapShotCode, message: msg } = await this.saveImage_(code); |
| | | // callback({ snapShotCode, message: msg }); |
| | | callback({ base64Data: code, message }); |
| | | break; |
| | | } |
| | | case 'onUserVideoSizeChanged': { |
| | | callback(data); |
| | | break; |
| | | } |
| | | case 'onStart': { |
| | | callback({ id: code, errCode: message }); |
| | | break; |
| | | } |
| | | case 'onPlayProgress': { |
| | | callback({ id: code, curPtsMS: message, durationMS: extraInfo }); |
| | | break; |
| | | } |
| | | case 'onComplete': { |
| | | callback({ id: code, errCode: message }); |
| | | break; |
| | | } |
| | | case 'onConnectOtherRoom': { |
| | | // 拿不到 userid, 为了和 native 参数保持一致,所以空字符串代替 |
| | | callback({ userId: '', errCode: code, errMsg: message }); |
| | | break; |
| | | } |
| | | case 'onDisconnectOtherRoom': { |
| | | callback({ errCode: code, errMsg: message }); |
| | | break; |
| | | } |
| | | case 'onError': { |
| | | console.error(`onError: ${code}, ${message}, ${extraInfo}`); |
| | | callback(generateError_({ message }, code, extraInfo)); |
| | | break; |
| | | } |
| | | case 'onRecvCustomCmdMsg': { |
| | | const userId = code; |
| | | const cmdID = data[1] || 0; |
| | | const seq = data[2] || 0; |
| | | const message = data[3] || ""; |
| | | console.error(`onRecvCustomCmdMsg: ${userId}, ${cmdID}, ${seq}, ${message}`); |
| | | callback({ userId, cmdID, seq, message }); |
| | | break; |
| | | } |
| | | default: { |
| | | callback({ code, message, extraInfo }); |
| | | } |
| | | } |
| | | }); |
| | | this.listenersMap_.set(event, nativeListener); // 多次设置同一个事件时,后面的 callback 覆盖前面 |
| | | TrtcEvent.addEventListener(event, nativeListener); |
| | | } |
| | | off(event) { |
| | | if (typeof event !== NAME.STRING) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the off method parameter types. event type is a ${typeof event} not a ${NAME.STRING}`, |
| | | }); |
| | | } |
| | | try { |
| | | if (event === '*') { |
| | | this.listenersMap_.forEach((value, key) => { |
| | | TrtcEvent.removeEventListener(key, value); |
| | | }); |
| | | this.listenersMap_.clear(); |
| | | } |
| | | else { |
| | | TrtcEvent.removeEventListener(event, this.listenersMap_.get(event)); |
| | | this.listenersMap_.delete(event); |
| | | } |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | enterRoom(params, scene) { |
| | | if (scene !== TRTCAppScene.TRTCAppSceneVideoCall && scene !== TRTCAppScene.TRTCAppSceneLIVE && scene !== TRTCAppScene.TRTCAppSceneAudioCall && scene !== TRTCAppScene.TRTCAppSceneVoiceChatRoom) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the enterRoom method parameters. scene is not of TRTCAppScene`, |
| | | }); |
| | | } |
| | | try { |
| | | const enterRoomParams = Object.assign(Object.assign({}, params), { role: params.role || TRTCRoleType.TRTCRoleAnchor, appScene: scene }); |
| | | TrtcNativeTrtcCloudModule.enterRoom(enterRoomParams); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | exitRoom() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.exitRoom(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | connectOtherRoom(params) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.connectOtherRoom(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | disconnectOtherRoom() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.disconnectOtherRoom(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | switchRole(role) { |
| | | if (role !== TRTCRoleType.TRTCRoleAnchor && role !== TRTCRoleType.TRTCRoleAudience) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the switchRole method parameter. role is not of TRTCRoleType`, |
| | | }); |
| | | } |
| | | try { |
| | | role && TrtcNativeTrtcCloudModule.switchRole(role); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | startLocalPreview(isFrontCamera = true, viewId) { |
| | | if (typeof isFrontCamera !== NAME.BOOLEAN || !viewId || typeof viewId !== NAME.STRING) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the startLocalPreview method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | let param = { isFrontCamera: !!isFrontCamera }; |
| | | param = viewId ? Object.assign(Object.assign({}, param), { userId: viewId }) : param; |
| | | TrtcNativeTrtcCloudModule.startLocalPreview(param); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setVideoEncoderParam(param) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setVideoEncoderParam(param); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopLocalPreview() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.stopLocalPreview(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | switchCamera(isFrontCamera) { |
| | | if (typeof isFrontCamera !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the switchCamera method parameter`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.switchCamera(isFrontCamera); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setLocalRenderParams(params) { |
| | | try { |
| | | const { rotation = TRTCVideoRotation.TRTCVideoRotation_0, fillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fill, mirrorType = TRTCVideoMirrorType.TRTCVideoMirrorType_Auto } = params; |
| | | TrtcNativeTrtcCloudModule.setLocalRenderParams({ |
| | | rotation, |
| | | fillMode, |
| | | mirrorType, |
| | | }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | muteLocalVideo(streamType, mute) { |
| | | if (streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub || typeof mute !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the muteLocalVideo method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.muteLocalVideo({ streamType, mute: !!mute }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | startRemoteView(userId, streamType, viewId) { |
| | | if (!userId || streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSmall && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub || !viewId) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the startRemoteView method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.startRemoteView({ userId, streamType, viewId }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopRemoteView(userId, streamType) { |
| | | if (!userId || streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSmall && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the stopRemoteView method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.stopRemoteView({ userId, streamType }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 远端渲染设置 |
| | | setRemoteRenderParams(userId, streamType, params) { |
| | | try { |
| | | if (!userId || (streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub)) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the snapshotVideo method parameters`, |
| | | }); |
| | | } |
| | | const { rotation = TRTCVideoRotation.TRTCVideoRotation_0, fillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fill, mirrorType = TRTCVideoMirrorType.TRTCVideoMirrorType_Auto } = params; |
| | | TrtcNativeTrtcCloudModule.setRemoteRenderParams({ |
| | | userId, |
| | | streamType, |
| | | rotation, |
| | | fillMode, |
| | | mirrorType |
| | | }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 设置视频编码器输出的画面方向 |
| | | setVideoEncoderRotation(rotation) { |
| | | if (typeof rotation !== NAME.NUMBER) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setVideoEncoderRotation method parameter`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setVideoEncoderRotation(rotation); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 设置编码器输出的画面镜像模式 |
| | | setVideoEncoderMirror(mirror) { |
| | | if (typeof mirror !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setVideoEncoderMirror method parameter`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setVideoEncoderMirror(mirror); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 设置重力感应的适配模式 |
| | | setGSensorMode(mode) { |
| | | if (typeof mode !== NAME.NUMBER) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setGSensorMode method parameter`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setGSensorMode(mode); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // 截图 |
| | | snapshotVideo(userId, streamType, sourceType) { |
| | | if (streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the snapshotVideo method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.snapshotVideo({ userId: userId || null, streamType, sourceType }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | startLocalAudio(quality = TRTCAudioQuality.TRTCAudioQualityDefault) { |
| | | if (quality !== TRTCAudioQuality.TRTCAudioQualitySpeech && quality !== TRTCAudioQuality.TRTCAudioQualityDefault && quality !== TRTCAudioQuality.TRTCAudioQualityMusic) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the startLocalAudio method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.startLocalAudio(quality); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopLocalAudio() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.stopLocalAudio(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | muteLocalAudio(mute) { |
| | | if (typeof mute !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the muteLocalAudio method parameters, mute type is a ${typeof mute} not a ${NAME.BOOLEAN}`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.muteLocalAudio(!!mute); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | muteRemoteAudio(userId, mute) { |
| | | if (typeof mute !== NAME.BOOLEAN || !userId) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the muteRemoteAudio method parameters`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.muteRemoteAudio({ userId, mute: !!mute }); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | muteAllRemoteAudio(mute) { |
| | | if (typeof mute !== NAME.BOOLEAN) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the muteAllRemoteAudio method parameters, mute type is a ${typeof mute} not a ${NAME.BOOLEAN}`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.muteAllRemoteAudio(!!mute); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setAudioRoute(route) { |
| | | if (route !== TRTCAudioRoute.TRTCAudioRouteSpeaker && route !== TRTCAudioRoute.TRTCAudioRouteEarpiece) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setAudioRoute method parameter, route is not of TRTCAudioRoute`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setAudioRoute(route); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | enableAudioVolumeEvaluation(interval) { |
| | | if (typeof interval !== NAME.NUMBER) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the enableAudioVolumeEvaluation method parameter, interval type is a ${typeof interval} not a ${NAME.NUMBER}`, |
| | | }); |
| | | } |
| | | try { |
| | | interval > 0 && TrtcNativeTrtcCloudModule.enableAudioVolumeEvaluation(interval); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 美颜 + 水印 |
| | | // |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | setBeautyStyle(beautyStyle) { |
| | | if (beautyStyle !== TRTCBeautyStyle.TRTCBeautyStyleSmooth && beautyStyle !== TRTCBeautyStyle.TRTCBeautyStyleNature && beautyStyle !== TRTCBeautyStyle.TRTCBeautyStylePitu) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setBeautyStyle method parameter, beautyStyle is not of TRTCBeautyStyle`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setBeautyStyle(beautyStyle); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setBeautyLevel(beautyLevel) { |
| | | if (typeof beautyLevel !== NAME.NUMBER || (beautyLevel < 0 || beautyLevel > 9)) { |
| | | throw new TrtcError({ |
| | | code: TXLiteJSError.INVALID_PARAMETER, |
| | | message: `${NAME.LOG_PREFIX} please check the setBeautyLevel method parameter, beautyLevel should in the range 0-9`, |
| | | }); |
| | | } |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setBeautyLevel(beautyLevel); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 背景音效 |
| | | // |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | startPlayMusic(musicParam) { |
| | | try { |
| | | const { id = 0 } = musicParam || {}; |
| | | TXAudioEffectManagerModule.startPlayMusic(Object.assign(Object.assign({}, musicParam), { ID: id })); // v1.2.0 的 iOS 解析的是 ID, v1.2.1 插件进行了修复 |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopPlayMusic(id) { |
| | | try { |
| | | TXAudioEffectManagerModule.stopPlayMusic(id); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | pausePlayMusic(id) { |
| | | try { |
| | | TXAudioEffectManagerModule.pausePlayMusic(id); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | resumePlayMusic(id) { |
| | | try { |
| | | TXAudioEffectManagerModule.resumePlayMusic(id); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 屏幕分享 |
| | | // |
| | | // /////////////////////////////////////////////////////////////////////////////// |
| | | setSubStreamEncoderParam(param) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setSubStreamEncoderParam(param); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | startScreenCapture(streamType = TRTCVideoStreamType.TRTCVideoStreamTypeSub, encParams = {}, shareParams = {}) { |
| | | try { |
| | | let platform = uni.getSystemInfoSync().platform; |
| | | if ((streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeSub && streamType !== TRTCVideoStreamType.TRTCVideoStreamTypeBig)) { |
| | | streamType = TRTCVideoStreamType.TRTCVideoStreamTypeSub; |
| | | } |
| | | const { enableForegroundService = true, appGroup } = shareParams; // 默认开启前台服务, 避免退后台后进程被杀 |
| | | const screenCaptureParams = Object.assign({ streamType }, encParams); |
| | | if (platform === NAME.ANDROID) { |
| | | TrtcNativeTrtcCloudModule.startScreenCapture(Object.assign(Object.assign({}, screenCaptureParams), { enableForegroundService })); |
| | | } |
| | | if (platform === NAME.IOS) { |
| | | if (typeof appGroup === 'string' && appGroup.length) { |
| | | // 开始全系统的屏幕分享(仅支持 iOS 11.0 及以上系统) |
| | | const params = { streamType, encParams, appGroup }; |
| | | TrtcNativeTrtcCloudModule.startScreenCaptureByReplaykit(params); |
| | | } |
| | | else { |
| | | // 开始应用内的屏幕分享(仅支持 iOS 13.0 及以上系统) |
| | | TrtcNativeTrtcCloudModule.startScreenCaptureInApp(screenCaptureParams); |
| | | } |
| | | } |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | stopScreenCapture() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.stopScreenCapture(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | pauseScreenCapture() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.pauseScreenCapture(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | resumeScreenCapture() { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.resumeScreenCapture(); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | callExperimentalAPI(params) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.callExperimentalAPI(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setSystemVolumeType(type) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setSystemVolumeType(type); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | setVideoMuteImage(fps, image) { |
| | | const params = { |
| | | fps, |
| | | filePath: image, |
| | | }; |
| | | try { |
| | | TrtcNativeTrtcCloudModule.setVideoMuteImage(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | enableEncSmallVideoStream(enable, smallVideoEncParam) { |
| | | const params = Object.assign({ enable }, smallVideoEncParam); |
| | | try { |
| | | TrtcNativeTrtcCloudModule.enableEncSmallVideoStream(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | sendCustomCmdMsg(params) { |
| | | try { |
| | | TrtcNativeTrtcCloudModule.sendCustomCmdMsg(params); |
| | | } |
| | | catch (error) { |
| | | throw generateError_(error); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | import { NAME, errorCodeUrl } from './constants.js'; |
| | | /** |
| | | * @namespace ErrorCode |
| | | * |
| | | * @description 错误码、警告码和事件列表 |
| | | */ |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // (一)错误码(严重) |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * @memberof ErrorCode |
| | | * @typedef 错误码(严重) |
| | | * @description SDK 错误码(严重)对照表 |
| | | * | 符号 | 值 | 含义 | |
| | | * |---|---|---| |
| | | * |ERR_NULL|0|无错误| |
| | | * |ERR_ROOM_ENTER_FAIL|-3301|进入房间失败| |
| | | * |ERR_ENTER_ROOM_PARAM_NULL|-3316|进房参数为空,请检查 enterRoom:appScene: 接口调用是否传入有效的 param| |
| | | * |ERR_SDK_APPID_INVALID|-3317|进房参数 sdkAppId 错误| |
| | | * |ERR_ROOM_ID_INVALID|-3318|进房参数 roomId 错误| |
| | | * |ERR_USER_ID_INVALID|-3319|进房参数 userID 不正确| |
| | | * |ERR_USER_SIG_INVALID|-3320|进房参数 userSig 不正确| |
| | | * |ERR_ROOM_REQUEST_ENTER_ROOM_TIMEOUT|-3308|请求进房超时,请检查网络| |
| | | * |ERR_SERVER_INFO_SERVICE_SUSPENDED|-100013|服务不可用。请检查:套餐包剩余分钟数是否大于0,腾讯云账号是否欠费| |
| | | * |ERR_ROOM_REQUEST_QUIT_ROOM_TIMEOUT|-3325|请求退房超时| |
| | | * |ERR_CAMERA_START_FAIL|-1301|打开摄像头失败,例如在 Windows 或 Mac 设备,摄像头的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序| |
| | | * |ERR_CAMERA_NOT_AUTHORIZED|-1314|摄像头设备未授权,通常在移动设备出现,可能是权限被用户拒绝了| |
| | | * |ERR_CAMERA_SET_PARAM_FAIL|-1315|摄像头参数设置出错(参数不支持或其它)| |
| | | * |ERR_CAMERA_OCCUPY|-1316|摄像头正在被占用中,可尝试打开其他摄像头| |
| | | * |ERR_MIC_START_FAIL|-1302|打开麦克风失败,例如在 Windows 或 Mac 设备,麦克风的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序| |
| | | * |ERR_MIC_NOT_AUTHORIZED|-1317|麦克风设备未授权,通常在移动设备出现,可能是权限被用户拒绝了| |
| | | * |ERR_MIC_SET_PARAM_FAIL|-1318|麦克风设置参数失败| |
| | | * |ERR_MIC_OCCUPY|-1319|麦克风正在被占用中,例如移动设备正在通话时,打开麦克风会失败| |
| | | * |ERR_MIC_STOP_FAIL|-1320|停止麦克风失败| |
| | | * |ERR_SPEAKER_START_FAIL|-1321|打开扬声器失败,例如在 Windows 或 Mac 设备,扬声器的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序| |
| | | * |ERR_SPEAKER_SET_PARAM_FAIL|-1322|扬声器设置参数失败| |
| | | * |ERR_SPEAKER_STOP_FAIL|-1323|停止扬声器失败| |
| | | * |ERR_SCREEN_CAPTURE_START_FAIL|-1308|开始录屏失败,如果在移动设备出现,可能是权限被用户拒绝了,如果在 Windows 或 Mac 系统的设备出现,请检查录屏接口的参数是否符合要求| |
| | | * |ERR_SCREEN_CAPTURE_UNSURPORT|-1309|录屏失败,在 Android 平台,需要5.0以上的系统| |
| | | * |ERR_SERVER_CENTER_NO_PRIVILEDGE_PUSH_SUB_VIDEO|-102015|没有权限上行辅路| |
| | | * |ERR_SERVER_CENTER_ANOTHER_USER_PUSH_SUB_VIDEO|-102016|其他用户正在上行辅路| |
| | | * |ERR_VIDEO_ENCODE_FAIL|-1303|视频帧编码失败,例如 iOS 设备切换到其他应用时,硬编码器可能被系统释放,再切换回来时,硬编码器重启前,可能会抛出| |
| | | * |ERR_UNSUPPORTED_RESOLUTION|-1305|不支持的视频分辨率| |
| | | * |ERR_AUDIO_ENCODE_FAIL|-1304|音频帧编码失败,例如传入自定义音频数据,SDK 无法处理| |
| | | * |ERR_UNSUPPORTED_SAMPLERATE|-1306|不支持的音频采样率| |
| | | * |ERR_PIXEL_FORMAT_UNSUPPORTED|-1327|设置的 pixel format 不支持| |
| | | * |ERR_BUFFER_TYPE_UNSUPPORTED|-1328|设置的 buffer type 不支持| |
| | | * |ERR_PUBLISH_CDN_STREAM_REQUEST_TIME_OUT|-3321|旁路转推请求超时| |
| | | * |ERR_CLOUD_MIX_TRANSCODING_REQUEST_TIME_OUT|-3322|云端混流请求超时| |
| | | * |ERR_PUBLISH_CDN_STREAM_SERVER_FAILED|-3323|旁路转推回包异常| |
| | | * |ERR_CLOUD_MIX_TRANSCODING_SERVER_FAILED|-3324|云端混流回包异常| |
| | | * |ERR_ROOM_REQUEST_START_PUBLISHING_TIMEOUT|-3333|开始向腾讯云的直播 CDN 推流信令超时| |
| | | * |ERR_ROOM_REQUEST_START_PUBLISHING_ERROR|-3334|开始向腾讯云的直播 CDN 推流信令异常| |
| | | * |ERR_ROOM_REQUEST_STOP_PUBLISHING_TIMEOUT|-3335|停止向腾讯云的直播 CDN 推流信令超时| |
| | | * |ERR_ROOM_REQUEST_STOP_PUBLISHING_ERROR|-3336|停止向腾讯云的直播 CDN 推流信令异常| |
| | | * |ERR_ROOM_REQUEST_CONN_ROOM_TIMEOUT|-3326|请求连麦超时| |
| | | * |ERR_ROOM_REQUEST_DISCONN_ROOM_TIMEOUT|-3327|请求退出连麦超时| |
| | | * |ERR_ROOM_REQUEST_CONN_ROOM_INVALID_PARAM|-3328|无效参数| |
| | | * |ERR_CONNECT_OTHER_ROOM_AS_AUDIENCE|-3330|当前是观众角色,不能请求或断开跨房连麦,需要先 switchRole() 到主播| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_NOT_SUPPORT|-102031|不支持跨房间连麦| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_REACH_MAX_NUM|-102032|达到跨房间连麦上限| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_REACH_MAX_RETRY_TIMES|-102033|跨房间连麦重试次数耗尽| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_REQ_TIMEOUT|-102034|跨房间连麦请求超时| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_REQ|-102035|跨房间连麦请求格式错误| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_NO_SIG|-102036|跨房间连麦无签名| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_DECRYPT_SIG|-102037|跨房间连麦签名解密失败| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_NO_KEY|-102038|未找到跨房间连麦签名解密密钥| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_PARSE_SIG|-102039|跨房间连麦签名解析错误| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_INVALID_SIG_TIME|-102040|跨房间连麦签名时间戳错误| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_SIG_GROUPID|-102041|跨房间连麦签名不匹配| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_NOT_CONNED|-102042|本房间无连麦| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_USER_NOT_CONNED|-102043|本用户未发起连麦| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_FAILED|-102044|跨房间连麦失败| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CANCEL_FAILED|-102045|取消跨房间连麦失败| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_ROOM_NOT_EXIST|-102046|被连麦房间不存在| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_REACH_MAX_ROOM|-102047|被连麦房间达到连麦上限| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_NOT_EXIST|-102048|被连麦用户不存在| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_DELETED|-102049|被连麦用户已被删除| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_FULL|-102050|被连麦用户达到资源上限| |
| | | * |ERR_SERVER_CENTER_CONN_ROOM_INVALID_SEQ|-102051|连麦请求序号错乱| |
| | | */ |
| | | export const TXLiteAVError = { |
| | | /** 无错误 */ |
| | | ERR_NULL: 0, |
| | | /** 进入房间失败 */ |
| | | ERR_ROOM_ENTER_FAIL: -3301, |
| | | /** 进房参数为空,请检查 enterRoom:appScene: 接口调用是否传入有效的 param */ |
| | | ERR_ENTER_ROOM_PARAM_NULL: -3316, |
| | | /** 进房参数 sdkAppId 错误 */ |
| | | ERR_SDK_APPID_INVALID: -3317, |
| | | /** 进房参数 roomId 错误 */ |
| | | ERR_ROOM_ID_INVALID: -3318, |
| | | /** 进房参数 userID 不正确 */ |
| | | ERR_USER_ID_INVALID: -3319, |
| | | /** 进房参数 userSig 不正确 */ |
| | | ERR_USER_SIG_INVALID: -3320, |
| | | /** 请求进房超时,请检查网络 */ |
| | | ERR_ROOM_REQUEST_ENTER_ROOM_TIMEOUT: -3308, |
| | | /** 服务不可用。请检查:套餐包剩余分钟数是否大于0,腾讯云账号是否欠费 */ |
| | | ERR_SERVER_INFO_SERVICE_SUSPENDED: -100013, |
| | | /** 请求退房超时 */ |
| | | ERR_ROOM_REQUEST_QUIT_ROOM_TIMEOUT: -3325, |
| | | /** 打开摄像头失败,例如在 Windows 或 Mac 设备,摄像头的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序 */ |
| | | ERR_CAMERA_START_FAIL: -1301, |
| | | /** 摄像头设备未授权,通常在移动设备出现,可能是权限被用户拒绝了 */ |
| | | ERR_CAMERA_NOT_AUTHORIZED: -1314, |
| | | /** 摄像头参数设置出错(参数不支持或其它) */ |
| | | ERR_CAMERA_SET_PARAM_FAIL: -1315, |
| | | /** 摄像头正在被占用中,可尝试打开其他摄像头 */ |
| | | ERR_CAMERA_OCCUPY: -1316, |
| | | /** 打开麦克风失败,例如在 Windows 或 Mac 设备,麦克风的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序 */ |
| | | ERR_MIC_START_FAIL: -1302, |
| | | /** 麦克风设备未授权,通常在移动设备出现,可能是权限被用户拒绝了 */ |
| | | ERR_MIC_NOT_AUTHORIZED: -1317, |
| | | /** 麦克风设置参数失败 */ |
| | | ERR_MIC_SET_PARAM_FAIL: -1318, |
| | | /** 麦克风正在被占用中,例如移动设备正在通话时,打开麦克风会失败 */ |
| | | ERR_MIC_OCCUPY: -1319, |
| | | /** 停止麦克风失败 */ |
| | | ERR_MIC_STOP_FAIL: -1320, |
| | | /** 打开扬声器失败,例如在 Windows 或 Mac 设备,扬声器的配置程序(驱动程序)异常,禁用后重新启用设备,或者重启机器,或者更新配置程序 */ |
| | | ERR_SPEAKER_START_FAIL: -1321, |
| | | /** 扬声器设置参数失败 */ |
| | | ERR_SPEAKER_SET_PARAM_FAIL: -1322, |
| | | /** 停止扬声器失败 */ |
| | | ERR_SPEAKER_STOP_FAIL: -1323, |
| | | /** 开始录屏失败,如果在移动设备出现,可能是权限被用户拒绝了,如果在 Windows 或 Mac 系统的设备出现,请检查录屏接口的参数是否符合要求 */ |
| | | ERR_SCREEN_CAPTURE_START_FAIL: -1308, |
| | | /** 录屏失败,在 Android 平台,需要5.0以上的系统 */ |
| | | ERR_SCREEN_CAPTURE_UNSURPORT: -1309, |
| | | /** 没有权限上行辅路 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_PUSH_SUB_VIDEO: -102015, |
| | | /** 其他用户正在上行辅路 */ |
| | | ERR_SERVER_CENTER_ANOTHER_USER_PUSH_SUB_VIDEO: -102016, |
| | | /** 视频帧编码失败,例如 iOS 设备切换到其他应用时,硬编码器可能被系统释放,再切换回来时,硬编码器重启前,可能会抛出 */ |
| | | ERR_VIDEO_ENCODE_FAIL: -1303, |
| | | /** 音频帧编码失败,例如传入自定义音频数据,SDK 无法处理 */ |
| | | ERR_AUDIO_ENCODE_FAIL: -1304, |
| | | /** 不支持的视频分辨率 */ |
| | | ERR_UNSUPPORTED_RESOLUTION: -1305, |
| | | /** 不支持的音频采样率 */ |
| | | ERR_UNSUPPORTED_SAMPLERATE: -1306, |
| | | /** 设置的 pixel format 不支持 */ |
| | | ERR_PIXEL_FORMAT_UNSUPPORTED: -1327, |
| | | /** 设置的 buffer type 不支持 */ |
| | | ERR_BUFFER_TYPE_UNSUPPORTED: -1328, |
| | | /** 旁路转推请求超时 */ |
| | | ERR_PUBLISH_CDN_STREAM_REQUEST_TIME_OUT: -3321, |
| | | /** 云端混流请求超时 */ |
| | | ERR_CLOUD_MIX_TRANSCODING_REQUEST_TIME_OUT: -3322, |
| | | /** 旁路转推回包异常 */ |
| | | ERR_PUBLISH_CDN_STREAM_SERVER_FAILED: -3323, |
| | | /** 云端混流回包异常 */ |
| | | ERR_CLOUD_MIX_TRANSCODING_SERVER_FAILED: -3324, |
| | | /** 开始向腾讯云的直播 CDN 推流信令超时 */ |
| | | ERR_ROOM_REQUEST_START_PUBLISHING_TIMEOUT: -3333, |
| | | /** 开始向腾讯云的直播 CDN 推流信令异常 */ |
| | | ERR_ROOM_REQUEST_START_PUBLISHING_ERROR: -3334, |
| | | /** 停止向腾讯云的直播 CDN 推流信令超时 */ |
| | | ERR_ROOM_REQUEST_STOP_PUBLISHING_TIMEOUT: -3335, |
| | | /** 停止向腾讯云的直播 CDN 推流信令异常 */ |
| | | ERR_ROOM_REQUEST_STOP_PUBLISHING_ERROR: -3336, |
| | | /** 请求连麦超时 */ |
| | | ERR_ROOM_REQUEST_CONN_ROOM_TIMEOUT: -3326, |
| | | /** 请求退出连麦超时 */ |
| | | ERR_ROOM_REQUEST_DISCONN_ROOM_TIMEOUT: -3327, |
| | | /** 无效参数 */ |
| | | ERR_ROOM_REQUEST_CONN_ROOM_INVALID_PARAM: -3328, |
| | | /** 当前是观众角色,不能请求或断开跨房连麦,需要先 switchRole() 到主播 */ |
| | | ERR_CONNECT_OTHER_ROOM_AS_AUDIENCE: -3330, |
| | | /** 不支持跨房间连麦 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_NOT_SUPPORT: -102031, |
| | | /** 达到跨房间连麦上限 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_REACH_MAX_NUM: -102032, |
| | | /** 跨房间连麦重试次数耗尽 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_REACH_MAX_RETRY_TIMES: -102033, |
| | | /** 跨房间连麦请求超时 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_REQ_TIMEOUT: -102034, |
| | | /** 跨房间连麦请求格式错误 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_REQ: -102035, |
| | | /** 跨房间连麦无签名 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_NO_SIG: -102036, |
| | | /** 跨房间连麦签名解密失败 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_DECRYPT_SIG: -102037, |
| | | /** 未找到跨房间连麦签名解密密钥 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_NO_KEY: -102038, |
| | | /** 跨房间连麦签名解析错误 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_PARSE_SIG: -102039, |
| | | /** 跨房间连麦签名时间戳错误 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_INVALID_SIG_TIME: -102040, |
| | | /** 跨房间连麦签名不匹配 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_SIG_GROUPID: -102041, |
| | | /** 本房间无连麦 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_NOT_CONNED: -102042, |
| | | /** 本用户未发起连麦 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_USER_NOT_CONNED: -102043, |
| | | /** 跨房间连麦失败 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_FAILED: -102044, |
| | | /** 取消跨房间连麦失败 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CANCEL_FAILED: -102045, |
| | | /** 被连麦房间不存在 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_ROOM_NOT_EXIST: -102046, |
| | | /** 被连麦房间达到连麦上限 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_REACH_MAX_ROOM: -102047, |
| | | /** 被连麦用户不存在 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_NOT_EXIST: -102048, |
| | | /** 被连麦用户已被删除 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_DELETED: -102049, |
| | | /** 被连麦用户达到资源上限 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_CONNED_USER_FULL: -102050, |
| | | /** 连麦请求序号错乱 */ |
| | | ERR_SERVER_CENTER_CONN_ROOM_INVALID_SEQ: -102051, |
| | | /** 直播,推流出现网络断开,且经过多次重试无法恢复 */ |
| | | ERR_RTMP_PUSH_NET_DISCONNECT: -1307, |
| | | /** 直播,推流地址非法,例如不是 RTMP 协议的地址 */ |
| | | ERR_RTMP_PUSH_INVALID_ADDRESS: -1313, |
| | | /** 直播,连接推流服务器失败(若支持智能选路,IP 全部失败) */ |
| | | ERR_RTMP_PUSH_NET_ALLADDRESS_FAIL: -1324, |
| | | /** 直播,网络不可用,请确认 WiFi、移动数据或者有线网络是否正常 */ |
| | | ERR_RTMP_PUSH_NO_NETWORK: -1325, |
| | | /** 直播,服务器拒绝连接请求,可能是该推流地址已经被占用,或者 TXSecret 校验失败,或者是过期了,或者是欠费了 */ |
| | | ERR_RTMP_PUSH_SERVER_REFUSE: -1326, |
| | | /** 直播,网络断连,且经多次重连抢救无效,可以放弃治疗,更多重试请自行重启播放 */ |
| | | ERR_PLAY_LIVE_STREAM_NET_DISCONNECT: -2301, |
| | | /** 直播,获取加速拉流的地址失败 */ |
| | | ERR_GET_RTMP_ACC_URL_FAIL: -2302, |
| | | /** 播放的文件不存在 */ |
| | | ERR_FILE_NOT_FOUND: -2303, |
| | | /** H265 解码失败 */ |
| | | ERR_HEVC_DECODE_FAIL: -2304, |
| | | /** 点播,音视频流解密失败 */ |
| | | ERR_VOD_DECRYPT_FAIL: -2305, |
| | | /** 点播,获取点播文件信息失败 */ |
| | | ERR_GET_VODFILE_MEDIAINFO_FAIL: -2306, |
| | | /** 直播,切流失败(切流可以播放不同画面大小的视频) */ |
| | | ERR_PLAY_LIVE_STREAM_SWITCH_FAIL: -2307, |
| | | /** 直播,服务器拒绝连接请求 */ |
| | | ERR_PLAY_LIVE_STREAM_SERVER_REFUSE: -2308, |
| | | /** 直播,RTMPACC 低延时拉流失败,且经过多次重试无法恢复 */ |
| | | ERR_RTMP_ACC_FETCH_STREAM_FAIL: -2309, |
| | | /** 心跳失败,客户端定时向服务器发送数据包,告诉服务器自己活着,这个错误通常是发包超时 */ |
| | | ERR_ROOM_HEARTBEAT_FAIL: -3302, |
| | | /** 拉取接口机服务器地址失败 */ |
| | | ERR_ROOM_REQUEST_IP_FAIL: -3303, |
| | | /** 连接接口机服务器失败 */ |
| | | ERR_ROOM_CONNECT_FAIL: -3304, |
| | | /** 请求视频位失败 */ |
| | | ERR_ROOM_REQUEST_AVSEAT_FAIL: -3305, |
| | | /** 请求 token https 超时,请检查网络是否正常,或网络防火墙是否放行 https 访问 official.opensso.tencent-cloud.com:443 */ |
| | | ERR_ROOM_REQUEST_TOKEN_HTTPS_TIMEOUT: -3306, |
| | | /** 请求 IP 和 sig 超时,请检查网络是否正常,或网络防火墙是否放行 UDP 访问下列 IP 和域名 query.tencent-cloud.com:8000 162.14.23.140:8000 162.14.7.49:8000 */ |
| | | ERR_ROOM_REQUEST_IP_TIMEOUT: -3307, |
| | | /** 请求视频位超时 */ |
| | | ERR_ROOM_REQUEST_VIDEO_FLAG_TIMEOUT: -3309, |
| | | /** 请求视频数据超时 */ |
| | | ERR_ROOM_REQUEST_VIDEO_DATA_ROOM_TIMEOUT: -3310, |
| | | /** 请求修改视频能力项超时 */ |
| | | ERR_ROOM_REQUEST_CHANGE_ABILITY_TIMEOUT: -3311, |
| | | /** 请求状态上报超时 */ |
| | | ERR_ROOM_REQUEST_STATUS_REPORT_TIMEOUT: -3312, |
| | | /** 请求关闭视频超时 */ |
| | | ERR_ROOM_REQUEST_CLOSE_VIDEO_TIMEOUT: -3313, |
| | | /** 请求接收视频项超时 */ |
| | | ERR_ROOM_REQUEST_SET_RECEIVE_TIMEOUT: -3314, |
| | | /** 请求 token 无效参数,请检查 TRTCParams.userSig 是否填写正确 */ |
| | | ERR_ROOM_REQUEST_TOKEN_INVALID_PARAMETER: -3315, |
| | | /** 请求 AES TOKEN 时,server 返回的内容是空的 */ |
| | | ERR_ROOM_REQUEST_AES_TOKEN_RETURN_ERROR: -3329, |
| | | /** 请求接口机 IP 返回的列表为空的 */ |
| | | ERR_ACCIP_LIST_EMPTY: -3331, |
| | | /** 请求发送 Json 信令超时 */ |
| | | ERR_ROOM_REQUEST_SEND_JSON_CMD_TIMEOUT: -3332, |
| | | // Info 服务器(查询接口机 IP), 服务器错误码,数值范围[-100000, -110000] |
| | | /** server 解包错误,可能请求数据被篡改 */ |
| | | ERR_SERVER_INFO_UNPACKING_ERROR: -100000, |
| | | /** TOKEN 错误 */ |
| | | ERR_SERVER_INFO_TOKEN_ERROR: -100001, |
| | | /** 分配接口机错误 */ |
| | | ERR_SERVER_INFO_ALLOCATE_ACCESS_FAILED: -100002, |
| | | /** 生成签名错误 */ |
| | | ERR_SERVER_INFO_GENERATE_SIGN_FAILED: -100003, |
| | | /** https token 超时 */ |
| | | ERR_SERVER_INFO_TOKEN_TIMEOUT: -100004, |
| | | /** 无效的命令字 */ |
| | | ERR_SERVER_INFO_INVALID_COMMAND: -100005, |
| | | /** 权限位校验失败 */ |
| | | ERR_SERVER_INFO_PRIVILEGE_FLAG_ERROR: -100006, |
| | | /** https 请求时,生成加密 key 错误 */ |
| | | ERR_SERVER_INFO_GENERATE_KEN_ERROR: -100007, |
| | | /** https 请求时,生成 token 错误 */ |
| | | ERR_SERVER_INFO_GENERATE_TOKEN_ERROR: -100008, |
| | | /** 数据库查询失败(房间相关存储信息) */ |
| | | ERR_SERVER_INFO_DATABASE: -100009, |
| | | /** 房间号错误 */ |
| | | ERR_SERVER_INFO_BAD_ROOMID: -100010, |
| | | /** 场景或角色错误 */ |
| | | ERR_SERVER_INFO_BAD_SCENE_OR_ROLE: -100011, |
| | | /** 房间号转换出错 */ |
| | | ERR_SERVER_INFO_ROOMID_EXCHANGE_FAILED: -100012, |
| | | /** 房间号非法 */ |
| | | ERR_SERVER_INFO_STRGROUP_HAS_INVALID_CHARS: -100014, |
| | | /** 非法SDKAppid */ |
| | | ERR_SERVER_INFO_LACK_SDKAPPID: -100015, |
| | | /** 无效请求, 旧版 0x1 要求带 Token; ECDH 要求带 ECDH Publich Key; 两个都没有就按报错 */ |
| | | ERR_SERVER_INFO_INVALID: -100016, |
| | | /** 生成公钥失败 */ |
| | | ERR_SERVER_INFO_ECDH_GET_KEY: -100017, |
| | | /** 获取tinyid失败 */ |
| | | ERR_SERVER_INFO_ECDH_GET_TINYID: -100018, |
| | | // Access 接口机 |
| | | /** token 过期 */ |
| | | ERR_SERVER_ACC_TOKEN_TIMEOUT: -101000, |
| | | /** 签名错误 */ |
| | | ERR_SERVER_ACC_SIGN_ERROR: -101001, |
| | | /** 签名超时 */ |
| | | ERR_SERVER_ACC_SIGN_TIMEOUT: -101002, |
| | | /** 房间不存在 */ |
| | | ERR_SERVER_ACC_ROOM_NOT_EXIST: -101003, |
| | | /** 后台房间标识 roomId 错误 */ |
| | | ERR_SERVER_ACC_ROOMID: -101004, |
| | | /** 后台用户位置标识 locationId 错误 */ |
| | | ERR_SERVER_ACC_LOCATIONID: -101005, |
| | | // center 服务器(信令和流控处理等任务) |
| | | /** 后台错误 */ |
| | | ERR_SERVER_CENTER_SYSTEM_ERROR: -102000, |
| | | /** 无效的房间 Id */ |
| | | ERR_SERVER_CENTER_INVALID_ROOMID: -102001, |
| | | /** 创建房间失败 */ |
| | | ERR_SERVER_CENTER_CREATE_ROOM_FAILED: -102002, |
| | | /** 签名错误 */ |
| | | ERR_SERVER_CENTER_SIGN_ERROR: -102003, |
| | | /** 签名过期 */ |
| | | ERR_SERVER_CENTER_SIGN_TIMEOUT: -102004, |
| | | /** 房间不存在 */ |
| | | ERR_SERVER_CENTER_ROOM_NOT_EXIST: -102005, |
| | | /** 房间添加用户失败 */ |
| | | ERR_SERVER_CENTER_ADD_USER_FAILED: -102006, |
| | | /** 查找用户失败 */ |
| | | ERR_SERVER_CENTER_FIND_USER_FAILED: -102007, |
| | | /** 频繁切换终端 */ |
| | | ERR_SERVER_CENTER_SWITCH_TERMINATION_FREQUENTLY: -102008, |
| | | /** locationid 错误 */ |
| | | ERR_SERVER_CENTER_LOCATION_NOT_EXIST: -102009, |
| | | /** 没有权限创建房间 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_CREATE_ROOM: -102010, |
| | | /** 没有权限进入房间 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_ENTER_ROOM: -102011, |
| | | /** 辅路抢视频位、申请辅路请求类型参数错误 */ |
| | | ERR_SERVER_CENTER_INVALID_PARAMETER_SUB_VIDEO: -102012, |
| | | /** 没有权限上视频 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_PUSH_VIDEO: -102013, |
| | | /** 没有空闲路由表 */ |
| | | ERR_SERVER_CENTER_ROUTE_TABLE_ERROR: -102014, |
| | | /** 当前用户没有上行辅路 */ |
| | | ERR_SERVER_CENTER_NOT_PUSH_SUB_VIDEO: -102017, |
| | | /** 用户被删除状态 */ |
| | | ERR_SERVER_CENTER_USER_WAS_DELETED: -102018, |
| | | /** 没有权限请求视频 */ |
| | | ERR_SERVER_CENTER_NO_PRIVILEDGE_REQUEST_VIDEO: -102019, |
| | | /** 进房参数 bussInfo 错误 */ |
| | | ERR_SERVER_CENTER_INVALID_PARAMETER: -102023, |
| | | /** 请求 I 帧未知 opType */ |
| | | ERR_SERVER_CENTER_I_FRAME_UNKNOW_TYPE: -102024, |
| | | /** 请求 I 帧包格式错误 */ |
| | | ERR_SERVER_CENTER_I_FRAME_INVALID_PACKET: -102025, |
| | | /** 请求 I 帧目标用户不存在 */ |
| | | ERR_SERVER_CENTER_I_FRAME_DEST_USER_NOT_EXIST: -102026, |
| | | /** 请求 I 帧房间用户太多 */ |
| | | ERR_SERVER_CENTER_I_FRAME_ROOM_TOO_BIG: -102027, |
| | | /** 请求 I 帧参数错误 */ |
| | | ERR_SERVER_CENTER_I_FRAME_RPS_INVALID_PARAMETER: -102028, |
| | | /** 房间号非法 */ |
| | | ERR_SERVER_CENTER_INVALID_ROOM_ID: -102029, |
| | | /** 房间号超过限制 */ |
| | | ERR_SERVER_CENTER_ROOM_ID_TOO_LONG: -102030, |
| | | /** 房间满员 */ |
| | | ERR_SERVER_CENTER_ROOM_FULL: -102052, |
| | | /** json串解析失败 */ |
| | | ERR_SERVER_CENTER_DECODE_JSON_FAIL: -102053, |
| | | /** 未定义命令字 */ |
| | | ERR_SERVER_CENTER_UNKNOWN_SUB_CMD: -102054, |
| | | /** 未定义角色 */ |
| | | ERR_SERVER_CENTER_INVALID_ROLE: -102055, |
| | | /** 代理机超出限制 */ |
| | | ERR_SERVER_CENTER_REACH_PROXY_MAX: -102056, |
| | | //add by sunlitwang begin |
| | | /** 无法保存用户自定义recordId */ |
| | | ERR_SERVER_CENTER_RECORDID_STORE: -102057, |
| | | /** Protobuf序列化错误 */ |
| | | ERR_SERVER_CENTER_PB_SERIALIZE: -102058, |
| | | // https://cloud.tencent.com/document/product/269/1671#.E5.B8.90.E5.8F.B7.E7.B3.BB.E7.BB.9F , 帐号系统, 主要是70000 - 79999之间. |
| | | // 在请求 token 过程中,出现账号错误,SSO 返回的错误码,原为正数,现将其转换为负数。 |
| | | /** sig 过期,请尝试重新生成。如果是刚生成,就过期,请检查有效期填写的是否过小,或者填的 0 */ |
| | | ERR_SERVER_SSO_SIG_EXPIRED: -70001, |
| | | /** sig 校验失败,请确认下 sig 内容是否被截断,如缓冲区长度不够导致的内容截断 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_1: -70003, |
| | | /** sig 校验失败,请确认下 sig 内容是否被截断,如缓冲区长度不够导致的内容截断 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_2: -70004, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_3: -70005, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_4: -70006, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_5: -70007, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_6: -70008, |
| | | /** 用业务公钥验证 sig 失败,请确认生成的 usersig 使用的私钥和 sdkAppId 是否对应 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_7: -70009, |
| | | /** sig 校验失败,可用工具自行验证生成的 sig 是否正确 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_FAILED_8: -70010, |
| | | /** sig 中 identifier 与请求时的 identifier 不匹配,请检查登录时填写的 identifier 与 sig 中的是否一致 */ |
| | | ERR_SERVER_SSO_SIG_VERIFICATION_ID_NOT_MATCH: -70013, |
| | | /** sig 中 sdkAppId 与请求时的 sdkAppId 不匹配,请检查登录时填写的 sdkAppId 与 sig 中的是否一致 */ |
| | | ERR_SERVER_SSO_APPID_NOT_MATCH: -70014, |
| | | /** 内部第三方票据验证超时,请重试,如多次重试不成功,请@TLS 帐号支持,QQ 3268519604 */ |
| | | ERR_SERVER_SSO_VERIFICATION_EXPIRED: -70017, |
| | | /** 内部第三方票据验证超时,请重试,如多次重试不成功,请@TLS 帐号支持,QQ 3268519604 */ |
| | | ERR_SERVER_SSO_VERIFICATION_FAILED: -70018, |
| | | /** sdkAppId 未找到,请确认是否已经在腾讯云上配置 */ |
| | | ERR_SERVER_SSO_APPID_NOT_FOUND: -70020, |
| | | /** 帐号已被拉入黑名单,请联系 TLS 帐号支持 QQ 3268519604 */ |
| | | ERR_SERVER_SSO_ACCOUNT_IN_BLACKLIST: -70051, |
| | | /** usersig 已经失效,请重新生成,再次尝试 */ |
| | | ERR_SERVER_SSO_SIG_INVALID: -70052, |
| | | /** 安全原因被限制 */ |
| | | ERR_SERVER_SSO_LIMITED_BY_SECURITY: -70114, |
| | | /** 登录状态无效,请使用 usersig 重新鉴权 */ |
| | | ERR_SERVER_SSO_INVALID_LOGIN_STATUS: -70221, |
| | | /** sdkAppId 填写错误 */ |
| | | ERR_SERVER_SSO_APPID_ERROR: -70252, |
| | | /** 票据校验失败,请检查各项参数是否正确 */ |
| | | ERR_SERVER_SSO_TICKET_VERIFICATION_FAILED: -70346, |
| | | /** 票据因过期原因校验失败 */ |
| | | ERR_SERVER_SSO_TICKET_EXPIRED: -70347, |
| | | /** 创建账号数量超过已购买预付费数量限制 */ |
| | | ERR_SERVER_SSO_ACCOUNT_EXCEED_PURCHASES: -70398, |
| | | /** 服务器内部错误,请重试 */ |
| | | ERR_SERVER_SSO_INTERNAL_ERROR: -70500, |
| | | }; |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // (二)错误码(警告) |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * @memberof ErrorCode |
| | | * @typedef 错误码(警告) |
| | | * @description SDK 错误码(警告)对照表 |
| | | * | 符号 | 值 | 含义 | |
| | | * |---|---|---| |
| | | * |WARNING_HW_ENCODER_START_FAIL|1103|硬编码启动出现问题,自动切换到软编码| |
| | | * |WARNING_VIDEO_ENCODER_SW_TO_HW|1107|当前 CPU 使用率太高,无法满足软件编码需求,自动切换到硬件编码| |
| | | * |WARNING_INSUFFICIENT_CAPTURE_FPS|1108|摄像头采集帧率不足,部分自带美颜算法的 Android 手机上会出现| |
| | | * |WARNING_SW_ENCODER_START_FAIL|1109|软编码启动失败| |
| | | * |WARNING_REDUCE_CAPTURE_RESOLUTION|1110|摄像头采集分辨率被降低,以满足当前帧率和性能最优解。| |
| | | * |WARNING_VIDEO_FRAME_DECODE_FAIL|2101|当前视频帧解码失败| |
| | | * |WARNING_AUDIO_FRAME_DECODE_FAIL|2102|当前音频帧解码失败| |
| | | * |WARNING_VIDEO_PLAY_LAG|2105|当前视频播放出现卡顿| |
| | | * |WARNING_HW_DECODER_START_FAIL|2106|硬解启动失败,采用软解码| |
| | | * |WARNING_VIDEO_DECODER_HW_TO_SW|2108|当前流硬解第一个 I 帧失败,SDK 自动切软解| |
| | | * |WARNING_SW_DECODER_START_FAIL|2109|软解码器启动失败| |
| | | * |WARNING_VIDEO_RENDER_FAIL|2110|视频渲染失败| |
| | | * |WARNING_AUDIO_RECORDING_WRITE_FAIL|7001|音频录制写入文件失败| |
| | | * |WARNING_ROOM_DISCONNECT|5101|网络断开连接| |
| | | * |WARNING_IGNORE_UPSTREAM_FOR_AUDIENCE|6001|当前是观众角色,忽略上行音视频数据| |
| | | */ |
| | | export const TXLiteAVWarning = { |
| | | /** 硬编码启动出现问题,自动切换到软编码 */ |
| | | WARNING_HW_ENCODER_START_FAIL: 1103, |
| | | /** 当前 CPU 使用率太高,无法满足软件编码需求,自动切换到硬件编码 */ |
| | | WARNING_VIDEO_ENCODER_SW_TO_HW: 1107, |
| | | /** 摄像头采集帧率不足,部分自带美颜算法的 Android 手机上会出现 */ |
| | | WARNING_INSUFFICIENT_CAPTURE_FPS: 1108, |
| | | /** 软编码启动失败 */ |
| | | WARNING_SW_ENCODER_START_FAIL: 1109, |
| | | /** 摄像头采集分辨率被降低,以满足当前帧率和性能最优解。 */ |
| | | WARNING_REDUCE_CAPTURE_RESOLUTION: 1110, |
| | | /** 当前视频帧解码失败 */ |
| | | WARNING_VIDEO_FRAME_DECODE_FAIL: 2101, |
| | | /** 当前音频帧解码失败 */ |
| | | WARNING_AUDIO_FRAME_DECODE_FAIL: 2102, |
| | | /** 当前视频播放出现卡顿 */ |
| | | WARNING_VIDEO_PLAY_LAG: 2105, |
| | | /** 硬解启动失败,采用软解码 */ |
| | | WARNING_HW_DECODER_START_FAIL: 2106, |
| | | /** 当前流硬解第一个 I 帧失败,SDK 自动切软解 */ |
| | | WARNING_VIDEO_DECODER_HW_TO_SW: 2108, |
| | | /** 软解码器启动失败 */ |
| | | WARNING_SW_DECODER_START_FAIL: 2109, |
| | | /** 视频渲染失败 */ |
| | | WARNING_VIDEO_RENDER_FAIL: 2110, |
| | | /** 音频录制写入文件失败 */ |
| | | WARNING_AUDIO_RECORDING_WRITE_FAIL: 7001, |
| | | /** 网络断开连接 */ |
| | | WARNING_ROOM_DISCONNECT: 5101, |
| | | /** 当前是观众角色,忽略上行音视频数据 */ |
| | | WARNING_IGNORE_UPSTREAM_FOR_AUDIENCE: 6001, |
| | | /** 网络状况不佳:上行带宽太小,上传数据受阻 */ |
| | | WARNING_NET_BUSY: 1101, |
| | | /** 直播,网络断连, 已启动自动重连(自动重连连续失败超过三次会放弃) */ |
| | | WARNING_RTMP_SERVER_RECONNECT: 1102, |
| | | /** 直播,网络断连, 已启动自动重连(自动重连连续失败超过三次会放弃) */ |
| | | WARNING_LIVE_STREAM_SERVER_RECONNECT: 2103, |
| | | /** 网络来包不稳:可能是下行带宽不足,或由于主播端出流不均匀 */ |
| | | WARNING_RECV_DATA_LAG: 2104, |
| | | /** 直播,DNS 解析失败 */ |
| | | WARNING_RTMP_DNS_FAIL: 3001, |
| | | /** 直播,服务器连接失败 */ |
| | | WARNING_RTMP_SEVER_CONN_FAIL: 3002, |
| | | /** 直播,与 RTMP 服务器握手失败 */ |
| | | WARNING_RTMP_SHAKE_FAIL: 3003, |
| | | /** 直播,服务器主动断开 */ |
| | | WARNING_RTMP_SERVER_BREAK_CONNECT: 3004, |
| | | /** 直播,RTMP 读/写失败,将会断开连接 */ |
| | | WARNING_RTMP_READ_WRITE_FAIL: 3005, |
| | | /** 直播,RTMP 写失败(SDK 内部错误码,不会对外抛出) */ |
| | | WARNING_RTMP_WRITE_FAIL: 3006, |
| | | /** 直播,RTMP 读失败(SDK 内部错误码,不会对外抛出) */ |
| | | WARNING_RTMP_READ_FAIL: 3007, |
| | | /** 直播,超过30s 没有数据发送,主动断开连接 */ |
| | | WARNING_RTMP_NO_DATA: 3008, |
| | | /** 直播,connect 服务器调用失败(SDK 内部错误码,不会对外抛出) */ |
| | | WARNING_PLAY_LIVE_STREAM_INFO_CONNECT_FAIL: 3009, |
| | | /** 直播,连接失败,该流地址无视频(SDK 内部错误码,不会对外抛出) */ |
| | | WARNING_NO_STEAM_SOURCE_FAIL: 3010, |
| | | /** 网络断连,已启动自动重连 */ |
| | | WARNING_ROOM_RECONNECT: 5102, |
| | | /** 网络状况不佳:上行带宽太小,上传数据受阻 */ |
| | | WARNING_ROOM_NET_BUSY: 5103, |
| | | }; |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // (三)JS 封装层抛出的异常(严重) |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * @namespace ErrorCode |
| | | * @description 错误码 |
| | | */ |
| | | export const TXLiteJSError = { |
| | | /** |
| | | * 未知错误 |
| | | * @default 0xFFFF |
| | | * @memberof module:ErrorCode |
| | | */ |
| | | UNKNOWN: 0xffff, |
| | | /** |
| | | * 无效参数 |
| | | * |
| | | * @default 0x1000 |
| | | * @memberof module:ErrorCode |
| | | */ |
| | | INVALID_PARAMETER: 0x1000, |
| | | /** |
| | | * 非法操作 |
| | | * |
| | | * @default 0x1001 |
| | | * @memberof module:ErrorCode |
| | | */ |
| | | INVALID_OPERATION: 0x1001, |
| | | }; |
| | | const getErrorName = function (code) { |
| | | for (let key in TXLiteJSError) { |
| | | if (TXLiteJSError[key] === code) { |
| | | return key; |
| | | } |
| | | } |
| | | return 'UNKNOWN'; |
| | | }; |
| | | /** |
| | | * TrtcError 错误对象<br> |
| | | * @extends Error |
| | | * @namespace ErrorCode |
| | | */ |
| | | class TrtcError extends Error { |
| | | constructor({ code = TXLiteJSError.UNKNOWN, message, extraInfo }) { |
| | | if (extraInfo) { |
| | | const tempError = { |
| | | errCode: code, |
| | | errMsg: message, |
| | | extraInfo: Object.assign(Object.assign({}, extraInfo), { errCodeUrl: errorCodeUrl }), |
| | | }; |
| | | super(JSON.stringify(tempError)); |
| | | } |
| | | else { |
| | | super(message + |
| | | ` <${getErrorName(code)} 0x${code.toString(16)}>. Refer to: ${errorCodeUrl}`); |
| | | } |
| | | this.errCode = code; |
| | | this.errMsg = message; |
| | | this.extraInfo = Object.assign(Object.assign({}, extraInfo), { errCodeUrl: errorCodeUrl }); |
| | | } |
| | | /** |
| | | * 获取错误码<br> |
| | | * 详细错误码列表参见 {@link module:ErrorCode ErrorCode} |
| | | * @memberof TrtcError |
| | | */ |
| | | getCode() { |
| | | return this.errCode; |
| | | } |
| | | } |
| | | export default TrtcError; |
| | | export function generateError_(error, code = TXLiteJSError.UNKNOWN, extraInfo) { |
| | | return new TrtcError({ |
| | | code: error.code || code, |
| | | message: `${NAME.LOG_PREFIX}${error.message}`, |
| | | extraInfo, |
| | | }); |
| | | } |
| | | ; |
| New file |
| | |
| | | /** |
| | | * TRTC 关键类型定义<br> |
| | | * @description 分辨率、质量等级等枚举和常量值的定义 |
| | | */ |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【(一)视频相关枚举值定义】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 视频分辨率<br> |
| | | * 此处仅定义横屏分辨率(如 640 × 360),如需使用竖屏分辨率(如 360 × 640),需要同时指定 VideoResolutionMode 为 Portrait |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoResolution_HACK_JSDOC = { |
| | | /** 宽高比 1:1;分辨率 120x120;建议码率(VideoCall)80kbps; 建议码率(LIVE)120kbps */ |
| | | TRTCVideoResolution_120_120: 1, |
| | | /** 宽高比 1:1 分辨率 160x160;建议码率(VideoCall)100kbps; 建议码率(LIVE)150kbps */ |
| | | TRTCVideoResolution_160_160: 3, |
| | | /** 宽高比 1:1;分辨率 270x270;建议码率(VideoCall)200kbps; 建议码率(LIVE)300kbps */ |
| | | TRTCVideoResolution_270_270: 5, |
| | | /** 宽高比 1:1;分辨率 480x480;建议码率(VideoCall)350kbps; 建议码率(LIVE)500kbps */ |
| | | TRTCVideoResolution_480_480: 7, |
| | | /** 宽高比4:3;分辨率 160x120;建议码率(VideoCall)100kbps; 建议码率(LIVE)150kbps */ |
| | | TRTCVideoResolution_160_120: 50, |
| | | /** 宽高比 4:3;分辨率 240x180;建议码率(VideoCall)150kbps; 建议码率(LIVE)250kbps */ |
| | | TRTCVideoResolution_240_180: 52, |
| | | /** 宽高比 4:3;分辨率 280x210;建议码率(VideoCall)200kbps; 建议码率(LIVE)300kbps */ |
| | | TRTCVideoResolution_280_210: 54, |
| | | /** 宽高比 4:3;分辨率 320x240;建议码率(VideoCall)250kbps; 建议码率(LIVE)375kbps */ |
| | | TRTCVideoResolution_320_240: 56, |
| | | /** 宽高比 4:3;分辨率 400x300;建议码率(VideoCall)300kbps; 建议码率(LIVE)450kbps */ |
| | | TRTCVideoResolution_400_300: 58, |
| | | /** 宽高比 4:3;分辨率 480x360;建议码率(VideoCall)400kbps; 建议码率(LIVE)600kbps */ |
| | | TRTCVideoResolution_480_360: 60, |
| | | /** 宽高比 4:3;分辨率 640x480;建议码率(VideoCall)600kbps; 建议码率(LIVE)900kbps */ |
| | | TRTCVideoResolution_640_480: 62, |
| | | /** 宽高比 4:3;分辨率 960x720;建议码率(VideoCall)1000kbps; 建议码率(LIVE)1500kbps */ |
| | | TRTCVideoResolution_960_720: 64, |
| | | /** 宽高比 16:9;分辨率 160x90;建议码率(VideoCall)150kbps; 建议码率(LIVE)250kbps */ |
| | | TRTCVideoResolution_160_90: 100, |
| | | /** 宽高比 16:9;分辨率 256x144;建议码率(VideoCall)200kbps; 建议码率(LIVE)300kbps */ |
| | | TRTCVideoResolution_256_144: 102, |
| | | /** 宽高比 16:9;分辨率 320x180;建议码率(VideoCall)250kbps; 建议码率(LIVE)400kbps */ |
| | | TRTCVideoResolution_320_180: 104, |
| | | /** 宽高比 16:9;分辨率 480x270;建议码率(VideoCall)350kbps; 建议码率(LIVE)550kbps */ |
| | | TRTCVideoResolution_480_270: 106, |
| | | /** 宽高比 16:9;分辨率 640x360;建议码率(VideoCall)500kbps; 建议码率(LIVE)900kbps */ |
| | | TRTCVideoResolution_640_360: 108, |
| | | /** 宽高比 16:9;分辨率 960x540;建议码率(VideoCall)850kbps; 建议码率(LIVE)1300kbps */ |
| | | TRTCVideoResolution_960_540: 110, |
| | | /** 宽高比 16:9;分辨率 1280x720;建议码率(VideoCall)1200kbps; 建议码率(LIVE)1800kbps */ |
| | | TRTCVideoResolution_1280_720: 112, |
| | | /** 宽高比 16:9;分辨率 1920x1080;建议码率(VideoCall)2000kbps; 建议码率(LIVE)3000kbps */ |
| | | TRTCVideoResolution_1920_1080: 114, |
| | | }; |
| | | export var TRTCVideoResolution; |
| | | (function (TRTCVideoResolution) { |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_120_120"] = 1] = "TRTCVideoResolution_120_120"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_160_160"] = 3] = "TRTCVideoResolution_160_160"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_270_270"] = 5] = "TRTCVideoResolution_270_270"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_480_480"] = 7] = "TRTCVideoResolution_480_480"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_160_120"] = 50] = "TRTCVideoResolution_160_120"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_240_180"] = 52] = "TRTCVideoResolution_240_180"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_280_210"] = 54] = "TRTCVideoResolution_280_210"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_320_240"] = 56] = "TRTCVideoResolution_320_240"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_400_300"] = 58] = "TRTCVideoResolution_400_300"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_480_360"] = 60] = "TRTCVideoResolution_480_360"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_640_480"] = 62] = "TRTCVideoResolution_640_480"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_960_720"] = 64] = "TRTCVideoResolution_960_720"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_160_90"] = 100] = "TRTCVideoResolution_160_90"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_256_144"] = 102] = "TRTCVideoResolution_256_144"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_320_180"] = 104] = "TRTCVideoResolution_320_180"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_480_270"] = 106] = "TRTCVideoResolution_480_270"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_640_360"] = 108] = "TRTCVideoResolution_640_360"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_960_540"] = 110] = "TRTCVideoResolution_960_540"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_1280_720"] = 112] = "TRTCVideoResolution_1280_720"; |
| | | TRTCVideoResolution[TRTCVideoResolution["TRTCVideoResolution_1920_1080"] = 114] = "TRTCVideoResolution_1920_1080"; |
| | | })(TRTCVideoResolution || (TRTCVideoResolution = {})); |
| | | /** |
| | | * 视频分辨率模式<br> |
| | | * TRTCVideoResolution 中仅定义了横屏分辨率(如 640 × 360),如需使用竖屏分辨率(如 360 × 640),需要同时指定 TRTCVideoResolutionMode 为 Portrait |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoResolutionMode_HACK_JSDOC = { |
| | | /** 横屏分辨率 */ |
| | | TRTCVideoResolutionModeLandscape: 0, |
| | | /** 竖屏分辨率 */ |
| | | TRTCVideoResolutionModePortrait: 1, |
| | | }; |
| | | export var TRTCVideoResolutionMode; |
| | | (function (TRTCVideoResolutionMode) { |
| | | TRTCVideoResolutionMode[TRTCVideoResolutionMode["TRTCVideoResolutionModeLandscape"] = 0] = "TRTCVideoResolutionModeLandscape"; |
| | | TRTCVideoResolutionMode[TRTCVideoResolutionMode["TRTCVideoResolutionModePortrait"] = 1] = "TRTCVideoResolutionModePortrait"; |
| | | })(TRTCVideoResolutionMode || (TRTCVideoResolutionMode = {})); |
| | | ; |
| | | /** |
| | | * 视频流类型<br> |
| | | * TRTC 内部有三种不同的音视频流,分别是: |
| | | * - 高清大画面:一般用来传输摄像头的视频数据 |
| | | * - 低清小画面:小画面和大画面的内容相互,但是分辨率和码率都比大画面低,因此清晰度也更低 |
| | | * - 辅流画面:一般用于屏幕分享,同一时间在同一个房间中只允许一个用户发布辅流视频,其他用户必须要等该用户关闭之后才能发布自己的辅流 |
| | | * |
| | | * **Note:** |
| | | * - 不支持单独开启低清小画面,小画面必须依附于大画面而存在,SDK 会自动设定低清小画面的分辨率和码率 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoStreamType_HACK_JSDOC = { |
| | | /** 大画面视频流 */ |
| | | TRTCVideoStreamTypeBig: 0, |
| | | /** 小画面视频流 */ |
| | | TRTCVideoStreamTypeSmall: 1, |
| | | /** 辅流(屏幕分享) */ |
| | | TRTCVideoStreamTypeSub: 2, |
| | | }; |
| | | export var TRTCVideoStreamType; |
| | | (function (TRTCVideoStreamType) { |
| | | TRTCVideoStreamType[TRTCVideoStreamType["TRTCVideoStreamTypeBig"] = 0] = "TRTCVideoStreamTypeBig"; |
| | | TRTCVideoStreamType[TRTCVideoStreamType["TRTCVideoStreamTypeSmall"] = 1] = "TRTCVideoStreamTypeSmall"; |
| | | TRTCVideoStreamType[TRTCVideoStreamType["TRTCVideoStreamTypeSub"] = 2] = "TRTCVideoStreamTypeSub"; |
| | | })(TRTCVideoStreamType || (TRTCVideoStreamType = {})); |
| | | /** |
| | | * 画面来源<br> |
| | | * TRTC 内部有两种不同的画面来源,分别是: |
| | | * - TRTCSnapshotSourceTypeStream: 视频流画面 |
| | | * - TRTCSnapshotSourceTypeView: 视频渲染画面 |
| | | * |
| | | * **Note:** |
| | | * - 截取视频流画面(TRTCSnapshotSourceTypeStream)一般更清晰。 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCSnapshotSourceType_HACK_JSDOC = { |
| | | /** 视频流画面 */ |
| | | TRTCSnapshotSourceTypeStream: 0, |
| | | /** 视频渲染画面 */ |
| | | TRTCSnapshotSourceTypeView: 1, |
| | | }; |
| | | export var TRTCSnapshotSourceType; |
| | | (function (TRTCSnapshotSourceType) { |
| | | TRTCSnapshotSourceType[TRTCSnapshotSourceType["TRTCSnapshotSourceTypeStream"] = 0] = "TRTCSnapshotSourceTypeStream"; |
| | | TRTCSnapshotSourceType[TRTCSnapshotSourceType["TRTCSnapshotSourceTypeView"] = 1] = "TRTCSnapshotSourceTypeView"; |
| | | })(TRTCSnapshotSourceType || (TRTCSnapshotSourceType = {})); |
| | | /** |
| | | * 视频画面填充模式<br> |
| | | * 如果画面的显示分辨率不等于画面的原始分辨率,就需要您设置画面的填充模式: |
| | | * - TRTCVideoFillMode_Fill,图像铺满屏幕,超出显示视窗的视频部分将被截掉,所以画面显示可能不完整。 |
| | | * - TRTCVideoFillMode_Fit,图像长边填满屏幕,短边区域会被填充黑色,但画面的内容肯定是完整的。 |
| | | * - TRTCVideoFillMode_ScaleFill,缩放填充模式,即无论画面的宽高比,都会被拉伸或压缩以完全填充显示区域,此模式下画面宽高比可能会被改变,导致渲染画面变形 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoFillMode_HACK_JSDOC = { |
| | | /** 图像铺满屏幕,超出显示视窗的视频部分将被截掉 */ |
| | | TRTCVideoFillMode_Fill: 0, |
| | | /** 图像长边填满屏幕,短边区域会被填充黑色 */ |
| | | TRTCVideoFillMode_Fit: 1, |
| | | /** 缩放填充模式,即无论画面的宽高比,都会被拉伸或压缩以完全填充显示区域 */ |
| | | TRTCVideoFillMode_ScaleFill: 2, |
| | | }; |
| | | export var TRTCVideoFillMode; |
| | | (function (TRTCVideoFillMode) { |
| | | TRTCVideoFillMode[TRTCVideoFillMode["TRTCVideoFillMode_Fill"] = 0] = "TRTCVideoFillMode_Fill"; |
| | | TRTCVideoFillMode[TRTCVideoFillMode["TRTCVideoFillMode_Fit"] = 1] = "TRTCVideoFillMode_Fit"; |
| | | TRTCVideoFillMode[TRTCVideoFillMode["TRTCVideoFillMode_ScaleFill"] = 2] = "TRTCVideoFillMode_ScaleFill"; |
| | | })(TRTCVideoFillMode || (TRTCVideoFillMode = {})); |
| | | ; |
| | | /** |
| | | * 视频画面旋转方向<br> |
| | | * TRTC SDK 提供了对本地和远程画面的旋转角度设置 API,如下的旋转角度都是指顺时针方向的。 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoRotation_HACK_JSDOC = { |
| | | /** 顺时针旋转0度 */ |
| | | TRTCVideoRotation_0: 0, |
| | | /** 顺时针旋转90度 */ |
| | | TRTCVideoRotation_90: 1, |
| | | /** 顺时针旋转180度 */ |
| | | TRTCVideoRotation_180: 2, |
| | | /** 顺时针旋转270度 */ |
| | | TRTCVideoRotation_270: 3, |
| | | }; |
| | | export var TRTCVideoRotation; |
| | | (function (TRTCVideoRotation) { |
| | | TRTCVideoRotation[TRTCVideoRotation["TRTCVideoRotation_0"] = 0] = "TRTCVideoRotation_0"; |
| | | TRTCVideoRotation[TRTCVideoRotation["TRTCVideoRotation_90"] = 1] = "TRTCVideoRotation_90"; |
| | | TRTCVideoRotation[TRTCVideoRotation["TRTCVideoRotation_180"] = 2] = "TRTCVideoRotation_180"; |
| | | TRTCVideoRotation[TRTCVideoRotation["TRTCVideoRotation_270"] = 3] = "TRTCVideoRotation_270"; |
| | | })(TRTCVideoRotation || (TRTCVideoRotation = {})); |
| | | /** |
| | | * 画面渲染镜像类型<br> |
| | | * TRTC 的画面镜像提供下列设置模式 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCVideoMirrorType_HACK_JSDOC = { |
| | | /** 只适用于移动端, 本地预览时,前置摄像头镜像,后置摄像头不镜像 */ |
| | | TRTCVideoMirrorType_Auto: 0, |
| | | /** 所有画面均镜像 */ |
| | | TRTCVideoMirrorType_Enable: 1, |
| | | /** 所有画面均不镜像 */ |
| | | TRTCVideoMirrorType_Disable: 2 |
| | | }; |
| | | export var TRTCVideoMirrorType; |
| | | (function (TRTCVideoMirrorType) { |
| | | TRTCVideoMirrorType[TRTCVideoMirrorType["TRTCVideoMirrorType_Auto"] = 0] = "TRTCVideoMirrorType_Auto"; |
| | | TRTCVideoMirrorType[TRTCVideoMirrorType["TRTCVideoMirrorType_Enable"] = 1] = "TRTCVideoMirrorType_Enable"; |
| | | TRTCVideoMirrorType[TRTCVideoMirrorType["TRTCVideoMirrorType_Disable"] = 2] = "TRTCVideoMirrorType_Disable"; |
| | | })(TRTCVideoMirrorType || (TRTCVideoMirrorType = {})); |
| | | /** |
| | | * 美颜(磨皮)算法<br> |
| | | * TRTC SDK 内置了多种不同的磨皮算法,您可以选择最适合您产品定位的方案。 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCBeautyStyle_HACK_JSDOC = { |
| | | /** 光滑,算法比较激进,磨皮效果比较明显,适用于秀场直播 */ |
| | | TRTCBeautyStyleSmooth: 0, |
| | | /** 自然,算法更多地保留了面部细节,磨皮效果更加自然,适用于绝大多数直播场景 */ |
| | | TRTCBeautyStyleNature: 1, |
| | | /** 优图,由优图实验室提供,磨皮效果介于光滑和自然之间,比光滑保留更多皮肤细节,比自然磨皮程度更高 */ |
| | | TRTCBeautyStylePitu: 2, |
| | | }; |
| | | export var TRTCBeautyStyle; |
| | | (function (TRTCBeautyStyle) { |
| | | TRTCBeautyStyle[TRTCBeautyStyle["TRTCBeautyStyleSmooth"] = 0] = "TRTCBeautyStyleSmooth"; |
| | | TRTCBeautyStyle[TRTCBeautyStyle["TRTCBeautyStyleNature"] = 1] = "TRTCBeautyStyleNature"; |
| | | TRTCBeautyStyle[TRTCBeautyStyle["TRTCBeautyStylePitu"] = 2] = "TRTCBeautyStylePitu"; |
| | | })(TRTCBeautyStyle || (TRTCBeautyStyle = {})); |
| | | /** |
| | | * 背景音效<br> |
| | | * @enum {Number} |
| | | */ |
| | | export class AudioMusicParam { |
| | | constructor(id, path, loopCount, publish, isShortFile, startTimeMS, endTimeMS) { |
| | | this.id = id; |
| | | this.path = path; |
| | | this.loopCount = loopCount; |
| | | this.publish = publish; |
| | | this.isShortFile = isShortFile; |
| | | this.startTimeMS = startTimeMS; |
| | | this.endTimeMS = endTimeMS; |
| | | } |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【(二)网络相关枚举值定义】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 应用场景<br> |
| | | * TRTC 可用于视频会议和在线直播等多种应用场景,针对不同的应用场景,TRTC SDK 的内部会进行不同的优化配置: |
| | | * - TRTCAppSceneVideoCall :视频通话场景,适合[1对1视频通话]、[300人视频会议]、[在线问诊]、[视频聊天]、[远程面试]等。 |
| | | * - TRTCAppSceneLIVE :视频互动直播,适合[视频低延时直播]、[十万人互动课堂]、[视频直播 PK]、[视频相亲房]、[互动课堂]、[远程培训]、[超大型会议]等。 |
| | | * - TRTCAppSceneAudioCall :语音通话场景,适合[1对1语音通话]、[300人语音会议]、[语音聊天]、[语音会议]、[在线狼人杀]等。 |
| | | * - TRTCAppSceneVoiceChatRoom:语音互动直播,适合:[语音低延时直播]、[语音直播连麦]、[语聊房]、[K 歌房]、[FM 电台]等。 |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCAppScene_HACK_JSDOC = { |
| | | /** |
| | | * 视频通话场景,支持720P、1080P高清画质,单个房间最多支持300人同时在线,最高支持50人同时发言。<br> |
| | | * 适合:[视频低延时直播]、[十万人互动课堂]、[视频直播 PK]、[视频相亲房]、[互动课堂]、[远程培训]、[超大型会议]等。<br> |
| | | * 注意:此场景下,您必须通过 TRTCParams 中的 role 字段指定当前用户的角色。 |
| | | */ |
| | | TRTCAppSceneVideoCall: 0, |
| | | /** |
| | | * 视频互动直播,支持平滑上下麦,切换过程无需等待,主播延时小于300ms;支持十万级别观众同时播放,播放延时低至1000ms。<br> |
| | | * 在线直播场景,内部编码器和网络协议优化侧重性能和兼容性,性能和清晰度表现更佳。 |
| | | */ |
| | | TRTCAppSceneLIVE: 1, |
| | | /** |
| | | * 语音通话场景,支持 48kHz,支持双声道。单个房间最多支持300人同时在线,最高支持50人同时发言。<br> |
| | | * 适合:[1对1语音通话]、[300人语音会议]、[语音聊天]、[语音会议]、[在线狼人杀]等。 |
| | | */ |
| | | TRTCAppSceneAudioCall: 2, |
| | | /** |
| | | * 语音互动直播,支持平滑上下麦,切换过程无需等待,主播延时小于300ms;支持十万级别观众同时播放,播放延时低至1000ms。<br> |
| | | * 适合:[语音低延时直播]、[语音直播连麦]、[语聊房]、[K 歌房]、[FM 电台]等。<br> |
| | | * 注意:此场景下,您必须通过 TRTCParams 中的 role 字段指定当前用户的角色。 |
| | | */ |
| | | TRTCAppSceneVoiceChatRoom: 3, |
| | | }; |
| | | export var TRTCAppScene; |
| | | (function (TRTCAppScene) { |
| | | TRTCAppScene[TRTCAppScene["TRTCAppSceneVideoCall"] = 0] = "TRTCAppSceneVideoCall"; |
| | | TRTCAppScene[TRTCAppScene["TRTCAppSceneLIVE"] = 1] = "TRTCAppSceneLIVE"; |
| | | TRTCAppScene[TRTCAppScene["TRTCAppSceneAudioCall"] = 2] = "TRTCAppSceneAudioCall"; |
| | | TRTCAppScene[TRTCAppScene["TRTCAppSceneVoiceChatRoom"] = 3] = "TRTCAppSceneVoiceChatRoom"; |
| | | })(TRTCAppScene || (TRTCAppScene = {})); |
| | | /** |
| | | * 角色,仅适用于直播场景(TRTCAppSceneLIVE 和 TRTCAppSceneVoiceChatRoom)<br> |
| | | * 在直播场景中,多数用户只是观众,只有个别用户是主播,这种角色区分可以有利于 TRTC 进行更好的定向优化。 |
| | | * - Anchor:主播,可以上行视频和音频,一个房间里最多支持50个主播同时上行音视频。 |
| | | * - Audience:观众,只能观看,不能上行视频和音频,一个房间里的观众人数没有上限。 |
| | | * |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCRoleType_HACK_JSDOC = { |
| | | /** 主播 */ |
| | | TRTCRoleAnchor: 20, |
| | | /** 观众 */ |
| | | TRTCRoleAudience: 21, |
| | | }; |
| | | export var TRTCRoleType; |
| | | (function (TRTCRoleType) { |
| | | TRTCRoleType[TRTCRoleType["TRTCRoleAnchor"] = 20] = "TRTCRoleAnchor"; |
| | | TRTCRoleType[TRTCRoleType["TRTCRoleAudience"] = 21] = "TRTCRoleAudience"; |
| | | })(TRTCRoleType || (TRTCRoleType = {})); |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【(三)音频相关枚举值定义】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 音频质量<br> |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCAudioQuality_HACK_JSDOC = { |
| | | /** 人声模式:适用于以人声沟通为主的应用场景,该模式下音频传输的抗性较强,TRTC 会通过各种人声处理技术保障在弱网络环境下的流畅度最佳 */ |
| | | TRTCAudioQualitySpeech: 1, |
| | | /** 标准模式(或者默认模式):介于 Speech 和 Music 之间的档位,对音乐的还原度比人声模式要好,但传输数据量比音乐模式要低很多,对各种场景均有不错的适应性,如无特殊需求推荐选择之。 */ |
| | | TRTCAudioQualityDefault: 2, |
| | | /** 音乐模式:适用于对声乐要求很苛刻的场景,该模式下音频传输的数据量很大,TRTC 会通过各项技术确保音乐信号在各频段均能获得高保真的细节还原度 */ |
| | | TRTCAudioQualityMusic: 3 |
| | | }; |
| | | export var TRTCAudioQuality; |
| | | (function (TRTCAudioQuality) { |
| | | TRTCAudioQuality[TRTCAudioQuality["TRTCAudioQualitySpeech"] = 1] = "TRTCAudioQualitySpeech"; |
| | | TRTCAudioQuality[TRTCAudioQuality["TRTCAudioQualityDefault"] = 2] = "TRTCAudioQualityDefault"; |
| | | TRTCAudioQuality[TRTCAudioQuality["TRTCAudioQualityMusic"] = 3] = "TRTCAudioQualityMusic"; |
| | | })(TRTCAudioQuality || (TRTCAudioQuality = {})); |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【(四)TRTC 核心类型定义】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 进房相关参数<br> |
| | | * 只有该参数填写正确,才能顺利调用 enterRoom 进入 roomId 所指定的音视频房间。 |
| | | * @param {Number} sdkAppId - 【字段含义】应用标识(必填),腾讯视频云基于 sdkAppId 完成计费统计。<br> |
| | | * 【推荐取值】在腾讯云 [TRTC 控制台](https://console.cloud.tencent.com/rav/) 中创建应用,之后可以在账号信息页面中得到该 ID。<br> |
| | | * @param {String} userId - 【字段含义】用户标识(必填)。当前用户的 userId,相当于用户名,UTF-8编码。<br> |
| | | * 【推荐取值】如果一个用户在您的账号系统中的 ID 为“abc”,则 userId 即可设置为“abc”。<br> |
| | | * @param {String} userSig - 【字段含义】用户签名(必填),当前 userId 对应的验证签名,相当于登录密码。<br> |
| | | * 【推荐取值】请参考 [如何计算UserSig](https://cloud.tencent.com/document/product/647/17275)。<br> |
| | | * @param {Number} roomId - 【字段含义】房间号码(必填),指定房间号,在同一个房间里的用户(userId)可以彼此看到对方并进行视频通话, roomId 和 strRoomId 必须填一个, 若您选用 strRoomId,则 roomId 需要填写为0。<br> |
| | | * 【推荐取值】您可以随意指定,但请不要重复,如果您的用户账号 ID 是数字类型的,可以直接用创建者的用户 ID 作为 roomId。<br> |
| | | * @param {String} strRoomId - 【字段含义】字符串房间号码(选填),roomId 和 strRoomId 必须填一个。若两者都填,则优先选择 roomId。<br> |
| | | * 【推荐取值】您可以随意指定,但请不要重复。<br> |
| | | * @param {TRTCRoleType} role - 【字段含义】直播场景下的角色,仅适用于直播场景(TRTCAppSceneLIVE 和 TRTCAppSceneVoiceChatRoom),视频通话场景下指定无效。<br> |
| | | * 【推荐取值】默认值:主播(TRTCRoleAnchor)<br> |
| | | * @param {String} privateMapKey - 【字段含义】房间签名(非必填),如果您希望某个房间只能让特定的某些 userId 进入,就需要使用 privateMapKey 进行权限保护。<br> |
| | | * 【推荐取值】仅建议有高级别安全需求的客户使用,参考文档:[进房权限保护](https://cloud.tencent.com/document/product/647/32240)<br> |
| | | * @param {String} businessInfo - 【字段含义】业务数据(非必填),某些非常用的高级特性才需要用到此字段。<br> |
| | | * 【推荐取值】不建议使用<br> |
| | | * @param {String} streamId - 【字段含义】绑定腾讯云直播 CDN 流 ID[非必填],设置之后,您就可以在腾讯云直播 CDN 上通过标准直播方案(FLV或HLS)播放该用户的音视频流。<br> |
| | | * 【推荐取值】限制长度为64字节,可以不填写,一种推荐的方案是使用 “sdkappid_roomid_userid_main” 作为 streamid,这样比较好辨认且不会在您的多个应用中发生冲突。<br> |
| | | * 【特殊说明】要使用腾讯云直播 CDN,您需要先在[控制台](https://console.cloud.tencent.com/trtc/) 中的功能配置页开启“启动自动旁路直播”开关。<br> |
| | | * 【参考文档】[CDN 旁路直播](https://cloud.tencent.com/document/product/647/16826)。 |
| | | * @param {String} userDefineRecordId - 【字段含义】设置云端录制完成后的回调消息中的 "userdefinerecordid" 字段内容,便于您更方便的识别录制回调。<br> |
| | | * 【推荐取值】限制长度为64字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。<br> |
| | | * 【参考文档】[云端录制](https://cloud.tencent.com/document/product/647/16823)。 |
| | | */ |
| | | export class TRTCParams { |
| | | constructor(sdkAppId, userId, roomId, userSig, strRoomId, privateMapKey, role, businessInfo, streamId, userDefineRecordId) { |
| | | this.sdkAppId = sdkAppId; |
| | | this.userId = userId; |
| | | this.roomId = roomId; |
| | | this.userSig = userSig; |
| | | this.strRoomId = strRoomId; |
| | | this.privateMapKey = privateMapKey; |
| | | this.role = role; |
| | | this.businessInfo = businessInfo; |
| | | this.streamId = streamId; |
| | | this.userDefineRecordId = userDefineRecordId; |
| | | } |
| | | } |
| | | /** |
| | | * 视频编码参数<br> |
| | | * 该设置决定了远端用户看到的画面质量(同时也是云端录制出的视频文件的画面质量)。 |
| | | * @param {TRTCVideoResolution} videoResolution - 【字段含义】 视频分辨率<br> |
| | | * 【推荐取值】 <br> |
| | | * - 视频通话建议选择360 × 640及以下分辨率,resMode 选择 Portrait。<br> |
| | | * - 手机直播建议选择 540 × 960,resMode 选择 Portrait。<br> |
| | | * - Window 和 iMac 建议选择 640 × 360 及以上分辨率,resMode 选择 Landscape。 |
| | | * 【特别说明】 TRTCVideoResolution 默认只能横屏模式的分辨率,例如640 × 360。<br> |
| | | * 如需使用竖屏分辨率,请指定 resMode 为 Portrait,例如640 × 360结合 Portrait 则为360 × 640。<br> |
| | | * @param {TRTCVideoResolutionMode} resMode - 【字段含义】分辨率模式(横屏分辨率 - 竖屏分辨率)<br> |
| | | * 【推荐取值】手机直播建议选择 Portrait,Window 和 Mac 建议选择 Landscape。<br> |
| | | * 【特别说明】如果 videoResolution 指定分辨率 640 × 360,resMode 指定模式为 Portrait,则最终编码出的分辨率为360 × 640。<br> |
| | | * @param {Number} videoFps - 【字段含义】视频采集帧率<br> |
| | | * 【推荐取值】15fps 或 20fps,10fps 以下会有轻微卡顿感,5fps 以下卡顿感明显,20fps 以上的帧率则过于浪费(电影的帧率也只有 24fps)。<br> |
| | | * 【特别说明】很多 Android 手机的前置摄像头并不支持15fps以上的采集帧率,部分过于突出美颜功能的 Android 手机前置摄像头的采集帧率可能低于10fps。<br> |
| | | * @param {Number} videoBitrate - 【字段含义】视频上行码率<br> |
| | | * 【推荐取值】推荐设置请参考本文件前半部分 TRTCVideoResolution 定义处的注释说明<br> |
| | | * 【特别说明】码率太低会导致视频中有很多的马赛克<br> |
| | | * @param {Number} minVideoBitrate -【字段含义】最低视频码率,SDK 会在网络不佳的情况下主动降低视频码率,最低会降至 minVideoBitrate 所设定的数值。 |
| | | * 【推荐取值】<br> |
| | | * - 如果您追求“允许卡顿但要保持清晰”的效果,可以设置 minVideoBitrate 为 videoBitrate 的 60%; |
| | | * - 如果您追求“允许模糊但要保持流畅”的效果,可以设置 minVideoBitrate 为 200kbps; |
| | | * - 如果您将 videoBitrate 和 minVideoBitrate 设置为同一个值,等价于关闭 SDK 的自适应调节能力; |
| | | * - 默认值:0,此时最低码率由 SDK 根据分辨率情况,自动设置合适的数值。<br> |
| | | * 【特别说明】<br> |
| | | * - 当您把分辨率设置的比较高时,minVideoBitrate 不适合设置的太低,否则会出现画面模糊和大范围的马赛克宏块。 |
| | | * 比如把分辨率设置为 720p,把码率设置为 200kbps,那么编码出的画面将会出现大范围区域性马赛克。 |
| | | * @param {Boolean} enableAdjustRes - 【字段含义】是否允许调整分辨率<br> |
| | | * 【推荐取值】 <br> |
| | | * - 手机直播建议选择 NO。<br> |
| | | * - 视频通话模式,若更关注流畅性,建议选择 YES,此时若遇到带宽有限的弱网,SDK 会自动降低分辨率以保障更好的流畅度(仅针对 TRTCVideoStreamTypeBig 生效)。 |
| | | * - 默认值:NO。<br> |
| | | * 【特别说明】若有录制需求,选择 YES 时,请确保通话过程中,调整分辨率不会影响您的录制效果。<br> |
| | | */ |
| | | export class TRTCVideoEncParam { |
| | | constructor(videoResolution = TRTCVideoResolution.TRTCVideoResolution_640_360, resMode = TRTCVideoResolutionMode.TRTCVideoResolutionModePortrait, videoFps = 15, videoBitrate = 550, minVideoBitrate = 0, enableAdjustRes = false) { |
| | | this.videoResolution = videoResolution; |
| | | this.videoResolutionMode = resMode; |
| | | this.videoFps = videoFps; |
| | | this.videoBitrate = videoBitrate; |
| | | this.minVideoBitrate = minVideoBitrate; |
| | | this.enableAdjustRes = enableAdjustRes; |
| | | } |
| | | } |
| | | ; |
| | | /** |
| | | * 画面渲染参数<br> |
| | | * 您可以通过设置此参数来控制画面的旋转、填充、镜像模式 |
| | | * @param {TRTCVideoRotation} rotation - 【字段含义】视频画面旋转方向 |
| | | * @param {TRTCVideoFillMode} fillMode - 【字段含义】视频画面填充模式 |
| | | * @param {TRTCVideoMirrorType} mirrorType - 【字段含义】画面渲染镜像类型 |
| | | */ |
| | | export class TRTCRenderParams { |
| | | constructor(rotation = TRTCVideoRotation.TRTCVideoRotation_0, fillMode = TRTCVideoFillMode.TRTCVideoFillMode_Fit, mirrorType = TRTCVideoMirrorType.TRTCVideoMirrorType_Disable) { |
| | | this.rotation = rotation; |
| | | this.fillMode = fillMode; |
| | | this.mirrorType = mirrorType; |
| | | } |
| | | } |
| | | /** |
| | | * 屏幕分享参数(仅适用于 Android 平台)<br> |
| | | * 该设置决定了远端用户看到的画面质量(同时也是云端录制出的视频文件的画面质量)。 |
| | | * @param {Boolean} enableForegroundService - 是否同时启用 SDK 内置的前台服务,停止屏幕分享时会停止该服务。 |
| | | * 从 Android 10 开始,如果 APP 的 targetSdkVersion 大于等于 29 时, |
| | | * 需要有 mediaProjection 类型的前台服务才能成功开始,否则会报 SecurityException。您可以自己启动一个前台服务,也可以使用 SDK 内置的前台服务。当使用内置的前台服务时 ** 您需要在 manifest.json 中添加以下内容:<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />** |
| | | * @param {String} appGroup 默认值为空,仅开启应用内屏幕分享;如需开启应用外屏幕分享,请填写 appGroup,同时在插件中配置相关信息,详见[功能接入/ios部分](https://cloud.tencent.com/document/product/647/113834) |
| | | */ |
| | | export class TRTCScreenShareParams { |
| | | constructor(enableForegroundService, appGroup) { |
| | | this.enableForegroundService = enableForegroundService; |
| | | this.appGroup = appGroup; |
| | | } |
| | | } |
| | | ; |
| | | /** |
| | | * 音频路由(即声音的播放模式)<br> |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCAudioRoute_HACK_JSDOC = { |
| | | /** 使用扬声器播放(即“免提”),扬声器位于手机底部,声音偏大,适合外放音乐 */ |
| | | TRTCAudioRouteSpeaker: 0, |
| | | /** 使用听筒播放,听筒位于手机顶部,声音偏小,适合需要保护隐私的通话场景 */ |
| | | TRTCAudioRouteEarpiece: 1, |
| | | }; |
| | | export var TRTCAudioRoute; |
| | | (function (TRTCAudioRoute) { |
| | | TRTCAudioRoute[TRTCAudioRoute["TRTCAudioRouteSpeaker"] = 0] = "TRTCAudioRouteSpeaker"; |
| | | TRTCAudioRoute[TRTCAudioRoute["TRTCAudioRouteEarpiece"] = 1] = "TRTCAudioRouteEarpiece"; |
| | | })(TRTCAudioRoute || (TRTCAudioRoute = {})); |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 【其它参数】 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | export var TRTCShareSource; |
| | | (function (TRTCShareSource) { |
| | | TRTCShareSource["InApp"] = "InApp"; |
| | | TRTCShareSource["ByReplaykit"] = "ByReplaykit"; |
| | | })(TRTCShareSource || (TRTCShareSource = {})); |
| | | /** |
| | | * 重力感应开关(仅适用于移动端)<br> |
| | | * @enum {Number} |
| | | */ |
| | | const TRTCGSensorMode_HACK_JSDOC = { |
| | | /** 不适配重力感应,该模式是桌面平台上的默认值,该模式下,当前用户发布出去的视频画面不受重力感应方向变化的影响。 */ |
| | | TRTC_GSENSOR_MODE_DISABLE: 0, |
| | | /** 适配重力感应,该模式是移动平台上的默认值,该模式下,当前用户发布出去的视频画面会跟随设备的重力感应方向进行相应的调整,同时本地预览画面保持方向不变。 |
| | | SDK 目前支持的一种适配模式是:当手机或 Pad 上下颠倒时,为了保证远端用户看到的画面方向正常,SDK 会自动将发布出去的画面上下旋转180度。如果您的 APP 的界面层开启了重力感应自适应,推荐使用 UIFixLayout 模式。 |
| | | */ |
| | | TRTC_GSENSOR_MODE_UIAUTOLAYOUT: 1, |
| | | }; |
| | | export var TRTCGSensorMode; |
| | | (function (TRTCGSensorMode) { |
| | | TRTCGSensorMode[TRTCGSensorMode["TRTC_GSENSOR_MODE_DISABLE"] = 0] = "TRTC_GSENSOR_MODE_DISABLE"; |
| | | TRTCGSensorMode[TRTCGSensorMode["TRTC_GSENSOR_MODE_UIAUTOLAYOUT"] = 1] = "TRTC_GSENSOR_MODE_UIAUTOLAYOUT"; |
| | | })(TRTCGSensorMode || (TRTCGSensorMode = {})); |
| | | /** |
| | | * 系统音量类型(仅适用于移动端)<br> |
| | | * - 通话音量:手机专门为接打电话所设计的音量类型,自带回声抵消(AEC)功能,并且支持通过蓝牙耳机上的麦克风进行拾音,缺点是音质比较一般。当您通过手机侧面的音量按键下调手机音量时,如果无法将其调至零(也就是无法彻底静音),说明您的手机当前处于通话音量。 |
| | | * - 媒体音量:手机专门为音乐场景所设计的音量类型,无法使用系统的 AEC 功能,并且不支持通过蓝牙耳机的麦克风进行拾音,但具备更好的音乐播放效果。当您通过手机侧面的音量按键下调手机音量时,如果能够将手机音量调至彻底静音,说明您的手机当前处于媒体音量。 |
| | | * @enum {Number} |
| | | */ |
| | | const TXSystemVolumeType_HACK_JSDOC = { |
| | | /** |
| | | * 自动切换模式: |
| | | * 也被称为“麦上通话,麦下媒体”,即主播上麦时使用通话音量,观众不上麦则使用媒体音量,适合在线直播场景。 |
| | | * 如果您在 enterRoom 时选择的场景为 TRTCAppSceneLIVE 或 TRTCAppSceneVoiceChatRoom,SDK 会自动使用该模式。 |
| | | */ |
| | | TXSystemVolumeTypeAuto: 0, |
| | | /** |
| | | * 全程媒体音量: |
| | | * 通话全程使用媒体音量,并不是非常常用的音量类型,适用于对音质要求比较苛刻的音乐场景中。 |
| | | * 如果您的用户大都使用外接设备(比如外接声卡)为主,可以使用该模式,否则请慎用。 |
| | | */ |
| | | TXSystemVolumeTypeMedia: 1, |
| | | /** |
| | | * 全程通话音量: |
| | | * 该方案的优势在于用户在上下麦时音频模块无需切换工作模式,可以做到无缝上下麦,适合于用户需要频繁上下麦的应用场景。 |
| | | * 如果您在 enterRoom 时选择的场景为 TRTCAppSceneVideoCall 或 TRTCAppSceneAudioCall,SDK 会自动使用该模式。 |
| | | */ |
| | | TXSystemVolumeTypeVOIP: 2, |
| | | }; |
| | | export var TXSystemVolumeType; |
| | | (function (TXSystemVolumeType) { |
| | | TXSystemVolumeType[TXSystemVolumeType["TXSystemVolumeTypeAuto"] = 0] = "TXSystemVolumeTypeAuto"; |
| | | TXSystemVolumeType[TXSystemVolumeType["TXSystemVolumeTypeMedia"] = 1] = "TXSystemVolumeTypeMedia"; |
| | | TXSystemVolumeType[TXSystemVolumeType["TXSystemVolumeTypeVOIP"] = 2] = "TXSystemVolumeTypeVOIP"; |
| | | })(TXSystemVolumeType || (TXSystemVolumeType = {})); |
| New file |
| | |
| | | export const NAME = { |
| | | ANDROID: 'android', |
| | | IOS: 'ios', |
| | | STRING: 'string', |
| | | FUNCTION: 'function', |
| | | BOOLEAN: 'boolean', |
| | | NUMBER: 'number', |
| | | LOG_PREFIX: '【UniApp-JS】', |
| | | }; |
| | | export const errorCodeUrl = 'https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/ErrorCode.html'; |
| New file |
| | |
| | | import TrtcCloudImpl from './TrtcCloudImpl.js'; |
| | | import { TRTCVideoStreamType } from './TrtcDefines.js'; |
| | | const version = '1.4.5'; |
| | | export * from './TrtcDefines.js'; |
| | | /** |
| | | * TrtcCloud |
| | | * |
| | | * @class TrtcCloud |
| | | */ |
| | | export default class TrtcCloud { |
| | | /** |
| | | * 创建 TrtcCloud 单例 |
| | | * |
| | | * @static |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * TrtcCloud.createInstance(); |
| | | */ |
| | | static createInstance() { |
| | | console.log('----------------------------------------------------------------'); |
| | | console.log(` SDK ${version} `); |
| | | console.log('----------------------------------------------------------------'); |
| | | return TrtcCloudImpl._createInstance(); |
| | | } |
| | | /** |
| | | * 销毁 TrtcCloud 单例 |
| | | * |
| | | * @static |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * TrtcCloud.destroyInstance(); |
| | | */ |
| | | static destroyInstance() { |
| | | return TrtcCloudImpl._destroyInstance(); |
| | | } |
| | | /** |
| | | * 设置 TrtcCloud 事件监听 |
| | | * |
| | | * @param {String} event 事件名称 |
| | | * @param {Function} callback 事件回调 |
| | | * @memberof TrtcCloud |
| | | * |
| | | * @example |
| | | * this.trtcCloud = TrtcCloud.createInstance(); // 创建 trtcCloud 实例 |
| | | * this.trtcCloud.on('onEnterRoom', (res) => {}); |
| | | */ |
| | | on(event, callback) { |
| | | return TrtcCloudImpl._getInstance().on(event, callback); |
| | | } |
| | | /** |
| | | * 取消事件绑定<br> |
| | | * |
| | | * @param {String} event 事件名称,传入通配符 '*' 会解除所有事件绑定。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.off('onEnterRoom'); |
| | | * |
| | | * this.trtcCloud.off('*'); // 取消所有绑定的事件 |
| | | */ |
| | | off(event) { |
| | | return TrtcCloudImpl._getInstance().off(event); |
| | | } |
| | | /** |
| | | * 进房<br> |
| | | * 调用接口后,您会收到来自 TRTCCallback 中的 [onEnterRoom(result)]{@link TRTCCallback#onEnterRoom} 回调 |
| | | * 如果加入成功,result 会是一个正数(result > 0),表示加入房间所消耗的时间,单位是毫秒(ms)。<br> |
| | | * 如果加入失败,result 会是一个负数(result < 0),表示进房失败的错误码。 |
| | | * |
| | | * * 参数 scene 的枚举值如下: |
| | | * - {@link TRTCAppSceneVideoCall}:<br> |
| | | * 视频通话场景,支持720P、1080P高清画质,单个房间最多支持300人同时在线,最高支持50人同时发言。<br> |
| | | * 适合:[1对1视频通话]、[300人视频会议]、[在线问诊]、[视频聊天]、[远程面试]等。<br> |
| | | * - {@link TRTCAppSceneAudioCall}:<br> |
| | | * 语音通话场景,支持 48kHz,支持双声道。单个房间最多支持300人同时在线,最高支持50人同时发言。<br> |
| | | * 适合:[1对1语音通话]、[300人语音会议]、[语音聊天]、[语音会议]、[在线狼人杀]等。<br> |
| | | * - {@link TRTCAppSceneLIVE}:<br> |
| | | * 视频互动直播,支持平滑上下麦,切换过程无需等待,主播延时小于300ms;支持十万级别观众同时播放,播放延时低至1000ms。<br> |
| | | * 适合:[视频低延时直播]、[十万人互动课堂]、[视频直播 PK]、[视频相亲房]、[互动课堂]、[远程培训]、[超大型会议]等。<br> |
| | | * - {@link TRTCAppSceneVoiceChatRoom}:<br> |
| | | * 语音互动直播,支持平滑上下麦,切换过程无需等待,主播延时小于300ms;支持十万级别观众同时播放,播放延时低至1000ms。<br> |
| | | * 适合:[语音低延时直播]、[语音直播连麦]、[语聊房]、[K 歌房]、[FM 电台]等。<br> |
| | | * |
| | | * **Note:** |
| | | * 1. 当 scene 选择为 TRTCAppSceneLIVE 或 TRTCAppSceneVoiceChatRoom 时,您必须通过 TRTCParams 中的 role 字段指定当前用户的角色。 |
| | | * 2. 不管进房是否成功,enterRoom 都必须与 exitRoom 配对使用,在调用 `exitRoom` 前再次调用 `enterRoom` 函数会导致不可预期的错误问题。 |
| | | * |
| | | * @param {TRTCParams} params - 进房参数 |
| | | * @param {Number} params.sdkAppId - 应用标识(必填) |
| | | * @param {String} params.userId - 用户标识(必填) |
| | | * @param {String} params.userSig - 用户签名(必填) |
| | | * @param {Number} params.roomId - 房间号码, roomId 和 strRoomId 必须填一个, 若您选用 strRoomId,则 roomId 需要填写为0。 |
| | | * @param {String} params.strRoomId - 字符串房间号码 [选填],在同一个房间内的用户可以看到彼此并进行视频通话, roomId 和 strRoomId 必须填一个。若两者都填,则优先选择 roomId |
| | | * @param {TRTCRoleType} params.role - 直播场景下的角色,默认值:主播 |
| | | * - TRTCRoleAnchor: 主播,可以上行视频和音频,一个房间里最多支持50个主播同时上行音视频。 |
| | | * - TRTCRoleAudience: 观众,只能观看,不能上行视频和音频,一个房间里的观众人数没有上限。 |
| | | * @param {String=} params.privateMapKey - 房间签名(非必填) |
| | | * @param {String=} params.businessInfo - 业务数据(非必填) |
| | | * @param {String=} params.streamId - 自定义 CDN 播放地址(非必填) |
| | | * @param {String=} params.userDefineRecordId - 设置云端录制完成后的回调消息中的 "userdefinerecordid" 字段内容,便于您更方便的识别录制回调(非必填) |
| | | * @param {TRTCAppScene} scene 应用场景,目前支持视频通话(TRTCAppSceneVideoCall)、语音通话(TRTCAppSceneAudioCall)、在线直播(TRTCAppSceneLIVE)、语音聊天室(VTRTCAppSceneVoiceChatRoom)四种场景, |
| | | * 详见 [TrtcDefines] 中 TRTCAppScene 参数定义 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCAppScene } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud = TrtcCloud.createInstance(); // 创建实例,只需创建一次 |
| | | * const params = { |
| | | * sdkAppId: 0, |
| | | * userId: 'xxx', |
| | | * roomId: 12345, |
| | | * userSig: 'xxx' |
| | | * }; |
| | | * this.trtcCloud.enterRoom(params, TRTCAppScene.TRTCAppSceneVideoCall); |
| | | */ |
| | | enterRoom(params, scene) { |
| | | return TrtcCloudImpl._getInstance().enterRoom(params, scene); |
| | | } |
| | | /** |
| | | * 退房<br> |
| | | * 执行退出房间的相关逻辑释放资源后,SDK 会通过 `onExitRoom()` 回调通知到您 |
| | | * |
| | | * **Note:** |
| | | * 1. 如果您要再次调用 `enterRoom()` 或者切换到其它的音视频 SDK,请等待 `onExitRoom()` 回调到来后再执行相关操作,否则可能会遇到如摄像头、麦克风设备被强占等各种异常问题。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.exitRoom(); |
| | | */ |
| | | exitRoom() { |
| | | return TrtcCloudImpl._getInstance().exitRoom(); |
| | | } |
| | | /** |
| | | * 切换角色,仅适用于直播场景(TRTCAppSceneLIVE 和 TRTCAppSceneVoiceChatRoom) |
| | | * |
| | | * 在直播场景下,一个用户可能需要在“观众”和“主播”之间来回切换。 |
| | | * 您可以在进房前通过 TRTCParams 中的 role 字段确定角色,也可以通过 switchRole 在进房后切换角色。 |
| | | * |
| | | * @param {TRTCRoleType} role - 目标角色,默认为主播 |
| | | * - TRTCRoleAnchor: 主播,可以上行视频和音频,一个房间里最多支持50个主播同时上行音视频。 |
| | | * - TRTCRoleAudience: 观众,只能观看,不能上行视频和音频,一个房间里的观众人数没有上限。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCRoleType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.switchRole(TRTCRoleType.TRTCRoleAudience); |
| | | */ |
| | | switchRole(role) { |
| | | return TrtcCloudImpl._getInstance().switchRole(role); |
| | | } |
| | | /** |
| | | * 请求跨房通话 |
| | | * |
| | | * 默认情况下,只有同一个房间中的用户之间可以进行音视频通话,不同的房间之间的音视频流是相互隔离的。 |
| | | * 使用该接口让身处两个不同房间中的主播进行跨房间的音视频流分享,从而让每个房间中的观众都能观看到这两个主播的音视频。 |
| | | * 跨房通话的请求结果会通过监听 [onConnectOtherRoom](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TRTCCallback.html#event:onConnectOtherRoom) 事件通知给您。 |
| | | * |
| | | * @param {Object} params - 跨房通话参数 |
| | | * - 如果对端的房间号为数字,那么传入的参数为 roomId。 |
| | | * - 如果对端的房间号为字符串,那么传入的参数为 strRoomId。 |
| | | * - 针对对端的房间号类型传递对应参数,不需要两个同时传递。具体请看 example 的使用。 |
| | | * @param {Number} params.roomId 跨房通话时对端的数字房间号 roomId(与 strRoomId 选填其中一个,不可同时传递) |
| | | * @param {String} params.strRoomId 跨房通话时对端的字符串房间号 strRoomId(与 roomId 选填其中一个,不可同时传递) |
| | | * @param {String} params.userId 跨房通话时对端的 userId(必填) |
| | | * |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.connectOtherRoom({"roomId": 1233, "userId": "user_11"}); |
| | | * this.trtcCloud.connectOtherRoom({"strRoomId": "1233", "userId": "user_22"}); |
| | | */ |
| | | connectOtherRoom(params) { |
| | | return TrtcCloudImpl._getInstance().connectOtherRoom(params); |
| | | } |
| | | /** |
| | | * 退出跨房通话 |
| | | * |
| | | * 退出跨房通话的请求结果会通过监听 [onDisconnectOtherRoom](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TRTCCallback.html#event:onDisconnectOtherRoom) 事件通知给您。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.disconnectOtherRoom(); |
| | | */ |
| | | disconnectOtherRoom() { |
| | | return TrtcCloudImpl._getInstance().disconnectOtherRoom(); |
| | | } |
| | | /** |
| | | * 开启本地视频的预览画面<br> |
| | | * 当开始渲染首帧摄像头画面时,您会收到 `onFirstVideoFrame(null)` 回调 |
| | | * |
| | | * @param {Boolean} isFrontCamera 前置、后置摄像头,true:前置摄像头;false:后置摄像头,**默认为 true** |
| | | * @param {String=} viewId 用于承载视频画面的渲染控件,使用原生插件中的 TRTCCloudUniPlugin-TXLocalViewComponent component,需要提供 viewId 属性值,例如 viewId=userId |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * // 预览本地画面 |
| | | * const viewId = this.userId; |
| | | * this.trtcCloud.startLocalPreview(true, viewId); |
| | | */ |
| | | startLocalPreview(isFrontCamera = true, viewId) { |
| | | return TrtcCloudImpl._getInstance().startLocalPreview(isFrontCamera, viewId); |
| | | } |
| | | /** |
| | | * 设置视频编码器的编码参数 |
| | | * - 该设置能够决定远端用户看到的画面质量,同时也能决定云端录制出的视频文件的画面质量。 |
| | | * @param {TRTCVideoEncParam} param 用于设置视频编码器的相关参数 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * |
| | | * import { TRTCVideoResolution, TRTCVideoResolutionMode, TRTCVideoEncParam } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const videoResolution = TRTCVideoResolution.TRTCVideoResolution_480_360; |
| | | * const videoResolutionMode = TRTCVideoResolutionMode.TRTCVideoResolutionModeLandscape; // 横屏采集 |
| | | * const videoFps = 15; |
| | | * const videoBitrate = 900; |
| | | * const minVideoBitrate = 200; |
| | | * const enableAdjustRes = false; |
| | | * // const param = new TRTCVideoEncParam(videoResolution, videoResolutionMode, videoFps, videoBitrate, minVideoBitrate, enableAdjustRes); // v1.1.0 方式 |
| | | * |
| | | * const param = { // v1.2.0 以上版本支持的方式 |
| | | * videoResolution, |
| | | * videoResolutionMode, |
| | | * videoFps, |
| | | * videoBitrate, |
| | | * minVideoBitrate, |
| | | * enableAdjustRes, |
| | | * }; |
| | | * |
| | | * this.trtcCloud.setVideoEncoderParam(param); |
| | | */ |
| | | setVideoEncoderParam(param) { |
| | | return TrtcCloudImpl._getInstance().setVideoEncoderParam(param); |
| | | } |
| | | /** |
| | | * 切换前置或后置摄像头 |
| | | * |
| | | * @param {Boolean} isFrontCamera 前置、后置摄像头,true:前置摄像头;false:后置摄像头 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * // 切换前置或后置摄像头 |
| | | * const isFrontCamera = true; |
| | | * this.trtcCloud.switchCamera(isFrontCamera); |
| | | */ |
| | | switchCamera(isFrontCamera) { |
| | | return TrtcCloudImpl._getInstance().switchCamera(isFrontCamera); |
| | | } |
| | | /** |
| | | * 停止本地视频采集及预览 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.stopLocalPreview(); |
| | | */ |
| | | stopLocalPreview() { |
| | | return TrtcCloudImpl._getInstance().stopLocalPreview(); |
| | | } |
| | | /** |
| | | * 设置本地画面的渲染参数,可设置的参数包括有:画面的旋转角度、填充模式以及左右镜像等。 |
| | | * @param {TRTCRenderParams} params - 本地图像的参数 |
| | | * @param {TRTCVideoRotation} params.rotation - 图像的顺时针旋转角度,支持90、180以及270旋转角度,默认值:TRTCVideoRotation.TRTCVideoRotation_0 |
| | | * @param {TRTCVideoFillMode} params.fillMode - 视频画面填充模式,填充(画面可能会被拉伸裁剪)或适应(画面可能会有黑边),默认值:TRTCVideoFillMode.TRTCVideoFillMode_Fill |
| | | * @param {TRTCVideoMirrorType} params.mirrorType - 画面镜像模式,默认值:TRTCVideoMirrorType.TRTCVideoMirrorType_Auto |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoRotation, TRTCVideoFillMode, TRTCVideoMirrorType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const renderParams = { |
| | | * rotation: TRTCVideoRotation.TRTCVideoRotation_0, |
| | | * fillMode: TRTCVideoFillMode.TRTCVideoFillMode_Fill, |
| | | * mirrorType: TRTCVideoMirrorType.TRTCVideoMirrorType_Auto |
| | | * }; |
| | | * this.trtcCloud.setLocalRenderParams(renderParams); |
| | | */ |
| | | setLocalRenderParams(params) { |
| | | return TrtcCloudImpl._getInstance().setLocalRenderParams(params); |
| | | } |
| | | /** |
| | | * 暂停/恢复发布本地的视频流 |
| | | * |
| | | * 该接口可以暂停(或恢复)发布本地的视频画面,暂停之后,同一房间中的其他用户将无法继续看到自己画面。 该接口在指定 TRTCVideoStreamTypeBig 时等效于 start/stopLocalPreview 这两个接口,但具有更好的响应速度。 因为 start/stopLocalPreview 需要打开和关闭摄像头,而打开和关闭摄像头都是硬件设备相关的操作,非常耗时。 相比之下,muteLocalVideo 只需要在软件层面对数据流进行暂停或者放行即可,因此效率更高,也更适合需要频繁打开关闭的场景。 当暂停/恢复发布指定 TRTCVideoStreamTypeBig 后,同一房间中的其他用户将会收到 onUserVideoAvailable 回调通知。 当暂停/恢复发布指定 TRTCVideoStreamTypeSub 后,同一房间中的其他用户将会收到 onUserSubStreamAvailable 回调通知。 |
| | | * @param {Number} streamType 要暂停/恢复的视频流类型(仅支持 TRTCVideoStreamTypeBig 和 TRTCVideoStreamTypeSub) |
| | | * @param {Boolean} mute - true:屏蔽;false:开启,默认值:false |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.muteLocalVideo(TRTCVideoStreamType.TRTCVideoStreamTypeBig, true); |
| | | */ |
| | | muteLocalVideo(streamType, mute) { |
| | | return TrtcCloudImpl._getInstance().muteLocalVideo(streamType, mute); |
| | | } |
| | | /** |
| | | * 显示远端视频或辅流<br> |
| | | * |
| | | * @param {String} userId 指定远端用户的 userId |
| | | * @param {Number} streamType 指定要观看 userId 的视频流类型 |
| | | * - 高清大画面:TRTCVideoStreamType.TRTCVideoStreamTypeBig |
| | | * - 低清小画面:TRTCVideoStreamType.TRTCVideoStreamTypeSmall |
| | | * - 辅流(屏幕分享):TRTCVideoStreamType.TRTCVideoStreamTypeSub |
| | | * @param {String} viewId 用于承载视频画面的渲染控件,使用原生插件中的 TRTCCloudUniPlugin-TXRemoteViewComponent component,需要提供 viewId 属性值,例如 viewId=userId |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoStreamType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const viewId = this.remoteUserId; |
| | | * this.trtcCloud.startRemoteView(userId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, viewId); |
| | | */ |
| | | startRemoteView(userId, streamType, viewId) { |
| | | return TrtcCloudImpl._getInstance().startRemoteView(userId, streamType, viewId); |
| | | } |
| | | /** |
| | | * 停止显示远端视频画面,同时不再拉取该远端用户的视频数据流<br> |
| | | * 指定要停止观看的 userId 的视频流类型 |
| | | * |
| | | * @param {String} userId 指定的远端用户 ID |
| | | * @param {Number} streamType |
| | | * - 高清大画面:TRTCVideoStreamType.TRTCVideoStreamTypeBig |
| | | * - 低清小画面:TRTCVideoStreamType.TRTCVideoStreamTypeSmall |
| | | * - 辅流(屏幕分享):TRTCVideoStreamType.TRTCVideoStreamTypeSub |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoStreamType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.stopRemoteView(remoteUserId, TRTCVideoStreamType.TRTCVideoStreamTypeBig); |
| | | */ |
| | | stopRemoteView(userId, streamType) { |
| | | return TrtcCloudImpl._getInstance().stopRemoteView(userId, streamType); |
| | | } |
| | | /** |
| | | * 设置远端画面的渲染参数,可设置的参数包括有:画面的旋转角度、填充模式以及左右镜像等。 |
| | | * @param {String} userId 远端用户 ID |
| | | * @param {Number} streamType 可以设置为主路画面(TRTCVideoStreamTypeBig)或辅路画面(TRTCVideoStreamTypeSub) |
| | | * @param {TRTCRenderParams} params - 图像的参数 |
| | | * @param {TRTCVideoRotation} params.rotation - 图像的顺时针旋转角度,支持90、180以及270旋转角度,默认值:TRTCVideoRotation.TRTCVideoRotation_0 |
| | | * @param {TRTCVideoFillMode} params.fillMode - 视频画面填充模式,填充(画面可能会被拉伸裁剪)或适应(画面可能会有黑边),默认值:TRTCVideoFillMode.TRTCVideoFillMode_Fill |
| | | * @param {TRTCVideoMirrorType} params.mirrorType - 画面镜像模式,默认值:TRTCVideoMirrorType.TRTCVideoMirrorType_Auto |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoRotation, TRTCVideoFillMode, TRTCVideoMirrorType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const renderParams = { |
| | | * rotation: TRTCVideoRotation.TRTCVideoRotation_0, |
| | | * fillMode: TRTCVideoFillMode.TRTCVideoFillMode_Fill, |
| | | * mirrorType: TRTCVideoMirrorType.TRTCVideoMirrorType_Auto |
| | | * }; |
| | | * this.trtcCloud.setRemoteRenderParams(userId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, renderParams); |
| | | */ |
| | | setRemoteRenderParams(userId, streamType, params) { } |
| | | /** |
| | | * 设置视频编码器输出的画面方向<br> |
| | | * 该设置不影响本地画面的预览方向,但会影响房间中其他用户所观看到(以及云端录制文件)的画面方向。 |
| | | * 当用户将手机或 Pad 上下颠倒时,由于摄像头的采集方向没有变,所以房间中其他用户所看到的画面会变成上下颠倒的, |
| | | * 在这种情况下,您可以通过调用该接口将 SDK 编码出的画面方向旋转180度,如此一来,房间中其他用户所看到的画面可保持正常的方向。 |
| | | * 如果您希望实现上述这种友好的交互体验,我们更推荐您直接调用 setGSensorMode 实现更加智能的方向适配,无需您手动调用本接口。 |
| | | * @param {Number} rotation 目前支持 0、90、180、270 两个旋转角度,默认值:TRTCVideoRotation_0,即不旋转。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoRotation } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.setVideoEncoderRotation(TRTCVideoRotation.TRTCVideoRotation_90); |
| | | */ |
| | | setVideoEncoderRotation(rotation) { |
| | | return TrtcCloudImpl._getInstance().setVideoEncoderRotation(rotation); |
| | | } |
| | | /** |
| | | * 设置编码器输出的画面镜像模式 |
| | | * @param {Boolean} mirror 是否开启远端镜像,true:开启远端画面镜像;false:关闭远端画面镜像,默认值:false。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.setVideoEncoderMirror(true); |
| | | */ |
| | | setVideoEncoderMirror(mirror) { |
| | | return TrtcCloudImpl._getInstance().setVideoEncoderMirror(mirror); |
| | | } |
| | | /** |
| | | * 设置重力感应的适配模式<br> |
| | | * 您可以通过本接口实现如下这种友好的交互体验: |
| | | * 当用户将手机或 Pad 上下颠倒时,由于摄像头的采集方向没有变,所以房间中其他用户所看到的画面会变成上下颠倒的, |
| | | * 在这种情况下,您可以通过调用该接口让 SDK 根据设备陀螺仪的朝向自动调整本地画面和编码器输出画面的旋转方向,以使远端观众可以看到正常朝向的画面。 |
| | | * @param {Number} mode 重力感应模式,详情请参见 TRTCGSensorMode,默认值:TRTCGSensorMode_UIAutoLayout。。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCGSensorMode } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.setGSensorMode(TRTCGSensorMode.TRTC_GSENSOR_MODE_DISABLE); |
| | | */ |
| | | setGSensorMode(mode) { |
| | | return TrtcCloudImpl._getInstance().setGSensorMode(mode); |
| | | } |
| | | /** |
| | | * 视频画面截图 |
| | | * |
| | | * 您可以通过本接口截取本地的视频画面,远端用户的主路画面以及远端用户的辅路(屏幕分享)画面。 |
| | | * |
| | | * @param {String | null} userId 用户 ID,如指定 null 表示截取本地的视频画面 |
| | | * @param {Number} streamType 视频流类型,可选择截取主路画面(TRTCVideoStreamTypeBig,常用于摄像头)或辅路画面(TRTCVideoStreamTypeSub,常用于屏幕分享) |
| | | * @param {TRTCSnapshotSourceType} sourceType 画面来源,可选择截取视频流画面(TRTCSnapshotSourceTypeStream)或视频渲染画面(TRTCSnapshotSourceTypeView),前者一般更清晰 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoStreamType } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.snapshotVideo(null, TRTCVideoStreamType.TRTCVideoStreamTypeBig, TRTCSnapshotSourceType.TRTCSnapshotSourceTypeStream); // 截取本地视频流画面 |
| | | * this.trtcCloud.snapshotVideo(this.remoteUserId, TRTCVideoStreamType.TRTCVideoStreamTypeBig, TRTCSnapshotSourceType.TRTCSnapshotSourceTypeView); // 截取远端指定用户视频渲染画面 |
| | | */ |
| | | snapshotVideo(userId, streamType, sourceType) { |
| | | return TrtcCloudImpl._getInstance().snapshotVideo(userId, streamType, sourceType); |
| | | } |
| | | /** |
| | | * 开启本地音频的采集和上行, 并设置音频质量<br> |
| | | * 该函数会启动麦克风采集,并将音频数据传输给房间里的其他用户。 SDK 不会默认开启本地音频采集和上行,您需要调用该函数开启,否则房间里的其他用户将无法听到您的声音<br> |
| | | * 主播端的音质越高,观众端的听感越好,但传输所依赖的带宽也就越高,在带宽有限的场景下也更容易出现卡顿 |
| | | * |
| | | * @param {TRTCAudioQuality} quality 声音音质 |
| | | * - TRTCAudioQualitySpeech,流畅:采样率:16k;单声道;音频裸码率:16kbps;适合语音通话为主的场景,比如在线会议,语音通话。 |
| | | * - TRTCAudioQualityDefault,默认:采样率:48k;单声道;音频裸码率:50kbps;SDK 默认的音频质量,如无特殊需求推荐选择之。 |
| | | * - TRTCAudioQualityMusic,高音质:采样率:48k;双声道 + 全频带;音频裸码率:128kbps;适合需要高保真传输音乐的场景,比如在线K歌、音乐直播等 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCAudioQuality } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.startLocalAudio(TRTCAudioQuality.TRTCAudioQualityDefault); |
| | | */ |
| | | startLocalAudio(quality) { |
| | | return TrtcCloudImpl._getInstance().startLocalAudio(quality); |
| | | } |
| | | /** |
| | | * 关闭本地音频的采集和上行<br> |
| | | * 当关闭本地音频的采集和上行,房间里的其它成员会收到 `onUserAudioAvailable(false)` 回调通知 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.stopLocalAudio(); |
| | | */ |
| | | stopLocalAudio() { |
| | | return TrtcCloudImpl._getInstance().stopLocalAudio(); |
| | | } |
| | | /** |
| | | * 静音本地的音频 |
| | | * |
| | | * 当静音本地音频后,房间里的其它成员会收到 onUserAudioAvailable(false) 回调通知。 |
| | | * 与 stopLocalAudio 不同之处在于,muteLocalAudio 并不会停止发送音视频数据,而是会继续发送码率极低的静音包。 |
| | | * 在对录制质量要求很高的场景中,选择 muteLocalAudio 是更好的选择,能录制出兼容性更好的 MP4 文件。 |
| | | * 这是由于 MP4 等视频文件格式,对于音频的连续性是要求很高的,简单粗暴地 stopLocalAudio 会导致录制出的 MP4 不易播放。 |
| | | * |
| | | * @param {Boolean} mute - true:屏蔽;false:开启,默认值:false |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.muteLocalAudio(true); |
| | | */ |
| | | muteLocalAudio(mute) { |
| | | return TrtcCloudImpl._getInstance().muteLocalAudio(mute); |
| | | } |
| | | /** |
| | | * 静音掉某一个用户的声音,同时不再拉取该远端用户的音频数据流 |
| | | * |
| | | * @param {String} userId - 用户 ID |
| | | * @param {Boolean} mute - true:静音;false:非静音 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.muteRemoteAudio('denny', true); |
| | | */ |
| | | muteRemoteAudio(userId, mute) { |
| | | return TrtcCloudImpl._getInstance().muteRemoteAudio(userId, mute); |
| | | } |
| | | /** |
| | | * 静音掉所有用户的声音,同时不再拉取该远端用户的音频数据流 |
| | | * |
| | | * @param {Boolean} mute - true:静音;false:非静音 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.muteAllRemoteAudio(true); |
| | | */ |
| | | muteAllRemoteAudio(mute) { |
| | | return TrtcCloudImpl._getInstance().muteAllRemoteAudio(mute); |
| | | } |
| | | /** |
| | | * 设置音频路由 |
| | | * |
| | | * 设置“音频路由”,即设置声音是从手机的扬声器还是从听筒中播放出来,因此该接口仅适用于手机等移动端设备。 手机有两个扬声器:一个是位于手机顶部的听筒,一个是位于手机底部的立体声扬声器。 |
| | | * 设置音频路由为听筒时,声音比较小,只有将耳朵凑近才能听清楚,隐私性较好,适合用于接听电话。 设置音频路由为扬声器时,声音比较大,不用将手机贴脸也能听清,因此可以实现“免提”的功能。 |
| | | * |
| | | * @param {TRTCAudioRoute} route 音频路由,即声音由哪里输出(扬声器、听筒), 默认值:TRTCAudioRoute.TRTCAudioRouteSpeaker(扬声器), |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCAudioRoute } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.setAudioRoute(TRTCAudioRoute.TRTCAudioRouteSpeaker); // TRTCAudioRoute.TRTCAudioRouteEarpiece (听筒) |
| | | */ |
| | | setAudioRoute(route) { |
| | | return TrtcCloudImpl._getInstance().setAudioRoute(route); |
| | | } |
| | | /** |
| | | * 启用或关闭音量大小提示 |
| | | * |
| | | * 开启此功能后,SDK 会在 onUserVoiceVolume() 中反馈对每一路声音音量大小值的评估。 |
| | | * |
| | | * **Note:** |
| | | * - 如需打开此功能,请在 startLocalAudio 之前调用才可以生效。 |
| | | * |
| | | * @param {Number} interval - 设置 onUserVoiceVolume 回调的触发间隔,单位为ms,最小间隔为100ms,如果小于等于0则会关闭回调,建议设置为300ms |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.enableAudioVolumeEvaluation(300); |
| | | */ |
| | | enableAudioVolumeEvaluation(interval) { |
| | | return TrtcCloudImpl._getInstance().enableAudioVolumeEvaluation(interval); |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 屏幕分享 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 设置屏幕分享(即辅路)的视频编码参数 |
| | | * |
| | | * 该接口可以设定远端用户所看到的屏幕分享(即辅路)的画面质量,同时也能决定云端录制出的视频文件中屏幕分享的画面质量。 请注意如下两个接口的差异: |
| | | * - setVideoEncoderParam 用于设置主路画面(TRTCVideoStreamTypeBig,一般用于摄像头)的视频编码参数。 |
| | | * - setSubStreamEncoderParam 用于设置辅路画面(TRTCVideoStreamTypeSub,一般用于屏幕分享)的视频编码参数。 |
| | | * |
| | | * **Note:** |
| | | * - 即使您使用主路传输屏幕分享(在调用 startScreenCapture 时设置 type=TRTCVideoStreamTypeBig),依然要使用 setSubStreamEncoderParam 设定屏幕分享的编码参数,而不要使用 setVideoEncoderParam |
| | | * @param {TRTCVideoEncParam} param 辅流编码参数,详情请参考 TRTCVideoEncParam。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const params = { |
| | | * videoResolution: TRTCVideoResolution.TRTCVideoResolution_640_360, |
| | | * videoResolutionMode: TRTCVideoResolutionMode.TRTCVideoResolutionModePortrait, |
| | | * videoFps: 15, |
| | | * videoBitrate: 900, |
| | | * minVideoBitrate: 200, |
| | | * enableAdjustRes: false, |
| | | * }; |
| | | * this.trtcCloud.setSubStreamEncoderParam(params); |
| | | */ |
| | | setSubStreamEncoderParam(param) { |
| | | return TrtcCloudImpl._getInstance().setSubStreamEncoderParam(param); |
| | | } |
| | | /** |
| | | * 启动屏幕分享 |
| | | * |
| | | * **Note:** |
| | | * - 一个用户同时最多只能上传一条主路(TRTCVideoStreamTypeBig)画面和一条辅路(TRTCVideoStreamTypeSub)画面, |
| | | * 默认情况下,屏幕分享使用辅路画面,如果使用主路画面,建议您提前停止摄像头采集(stopLocalPreview)避免相互冲突。 |
| | | * - **仅支持 iOS 13.0 及以上系统,进行应用内的屏幕分享;若要应用外屏幕分享,需填写 shareParams.appGroup 字段。** |
| | | * - **Android: UniApp 使用 SDK 内置的前台服务时,只需要将接口参数 enableForegroundService 设置为 true。** |
| | | * - **Android: UniApp 自己启动前台,需要在 mediaProject 类型的前台服务成功后再启动屏幕分享。** |
| | | * |
| | | * @param {Number} streamType 屏幕分享使用的线路,可以设置为主路(TRTCVideoStreamTypeBig)或者辅路(TRTCVideoStreamTypeSub),推荐使用 |
| | | * @param {TRTCVideoEncParam} encParams 屏幕分享的画面编码参数,可以设置为 null,表示让 SDK 选择最佳的编码参数(分辨率、码率等)。即使在调用 startScreenCapture 时设置 type=TRTCVideoStreamTypeBig,依然可以使用此接口更新屏幕分享的编码参数。 |
| | | * @param {TRTCScreenShareParams} shareParams 您可以通过其中的 enableForegroundService 参数启用 SDK 内置的前台服务; 当 appGroup 正确填写时,会开启 iOS 系统屏幕分享;如果不填写 appGroup, 则默认使用应用内屏幕分享。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoResolution, TRTCVideoResolutionMode, TRTCVideoStreamType} from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const encParams = { |
| | | * videoResolution: TRTCVideoResolution.TRTCVideoResolution_640_360, |
| | | * videoResolutionMode: TRTCVideoResolutionMode.TRTCVideoResolutionModePortrait, |
| | | * videoFps: 15, |
| | | * videoBitrate: 900, |
| | | * minVideoBitrate: 200, |
| | | * enableAdjustRes: false, |
| | | * }; |
| | | * const shareParams = { |
| | | * enableForegroundService: true, |
| | | * appGroup: 'xxx', |
| | | * }; |
| | | * this.trtcCloud.startScreenCapture(TRTCVideoStreamType.TRTCVideoStreamTypeSub, encParams, shareParams); |
| | | */ |
| | | startScreenCapture(streamType = TRTCVideoStreamType.TRTCVideoStreamTypeSub, encParams = null, shareParams = {}) { |
| | | return TrtcCloudImpl._getInstance().startScreenCapture(streamType, encParams, shareParams); |
| | | } |
| | | /** |
| | | * 停止屏幕分享 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.stopScreenCapture(); |
| | | */ |
| | | stopScreenCapture() { |
| | | return TrtcCloudImpl._getInstance().stopScreenCapture(); |
| | | } |
| | | /** |
| | | * 暂停屏幕分享 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.pauseScreenCapture(); |
| | | */ |
| | | pauseScreenCapture() { |
| | | return TrtcCloudImpl._getInstance().pauseScreenCapture(); |
| | | } |
| | | /** |
| | | * 恢复屏幕分享 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.resumeScreenCapture(); |
| | | */ |
| | | resumeScreenCapture() { |
| | | return TrtcCloudImpl._getInstance().resumeScreenCapture(); |
| | | } |
| | | /** |
| | | * 设置系统音量类型(仅适用于移动设备) |
| | | * |
| | | * @param {TXSystemVolumeType} type 系统音量类型 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.setSystemVolumeType(TXSystemVolumeType.TXSystemVolumeTypeAuto) |
| | | */ |
| | | setSystemVolumeType(type) { |
| | | return TrtcCloudImpl._getInstance().setSystemVolumeType(type); |
| | | } |
| | | /** |
| | | * 设置本地画面被暂停期间的替代图片 |
| | | * |
| | | * 当您调用 muteLocaLVideo(true)暂停本地画面时,您可以通过调用本接口设置一张替代图片,设置后,房间中的其他用户会看到这张替代图片,而不是黑屏画面。 |
| | | * |
| | | * @param {Number} fps 设置替代图片帧率,最小值为5,最大值为10,默认5。 |
| | | * @param {String} image 设置替代图片,空值代表在 muteLocalVideo 之后不再发送视频流数据,默认值为空。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.setVideoMuteImage(6, 'xxxx'); |
| | | */ |
| | | setVideoMuteImage(fps, image) { |
| | | return TrtcCloudImpl._getInstance().setVideoMuteImage(fps, image); |
| | | } |
| | | /** |
| | | * 开启大小画面双路编码模式 |
| | | * |
| | | * 开启双路编码模式后,当前用户的编码器会同时输出【高清大画面】和【低清小画面】两路视频流(但只有一路音频流)。 |
| | | * 如此以来,房间中的其他用户就可以根据自身的网络情况或屏幕大小选择订阅【高清大画面】或是【低清小画面】。 |
| | | |
| | | * @param {Boolean} enable 是否开启小画面编码,默认值:false。 |
| | | * @param {TRTCVideoEncParam} smallVideoEncParam 小流的视频参数。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCVideoEncParam, TRTCVideoResolution, TRTCVideoResolutionMode } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * this.trtcCloud.enableEncSmallVideoStream(true, {videoResolution: TRTCVideoResolution.TRTCVideoResolution_120_120, videoResolutionMode: TRTCVideoResolutionMode.TRTCVideoResolutionModeLandscape}) |
| | | */ |
| | | enableEncSmallVideoStream(enable, smallVideoEncParam) { |
| | | return TrtcCloudImpl._getInstance().enableEncSmallVideoStream(enable, smallVideoEncParam); |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 美颜 + 水印 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 设置美颜(磨皮)算法 |
| | | * TRTC 内置多种不同的磨皮算法,您可以选择最适合您产品定位的方案 |
| | | * |
| | | * **Note:** |
| | | * - 设置美颜前,先调用 `setBeautyLevel` 设置美颜级别。否则美颜级别为 0 表示关闭美颜 |
| | | * |
| | | * @param {TRTCBeautyStyle} beautyStyle 美颜风格,TRTCBeautyStyleSmooth:光滑;TRTCBeautyStyleNature:自然;TRTCBeautyStylePitu:优图 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { TRTCBeautyStyle } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const beautyLevel = 5; // 美颜级别,取值范围0 - 9; 0表示关闭,9表示效果最明显。 |
| | | * this.trtcCloud.setBeautyLevel(beautyLevel); |
| | | * this.trtcCloud.setBeautyStyle(TRTCBeautyStyle.TRTCBeautyStyleSmooth); |
| | | */ |
| | | setBeautyStyle(beautyStyle) { |
| | | return TrtcCloudImpl._getInstance().setBeautyStyle(beautyStyle); |
| | | } |
| | | /** |
| | | * 设置美颜级别 |
| | | * @param {Number} beautyLevel 美颜级别,取值范围0 - 9; 0表示关闭,9表示效果最明显。 |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const beautyLevel = 5; // 美颜级别,取值范围0 - 9; 0表示关闭,9表示效果最明显。 |
| | | * this.trtcCloud.setBeautyLevel(beautyLevel); |
| | | */ |
| | | setBeautyLevel(beautyLevel) { |
| | | return TrtcCloudImpl._getInstance().setBeautyLevel(beautyLevel); |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 背景音效 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 开始播放背景音乐 |
| | | * 每个音乐都需要您指定具体的 ID,您可以通过该 ID 对音乐的开始、停止、音量等进行设置。<br> |
| | | * **Note:** |
| | | * - 如果要多次播放同一首背景音乐,请不要每次播放都分配一个新的 ID,我们推荐使用相同的 ID。 |
| | | * - 若您希望同时播放多首不同的音乐,请为不同的音乐分配不同的 ID 进行播放。 |
| | | * - 如果使用同一个 ID 播放不同音乐,SDK 会先停止播放旧的音乐,再播放新的音乐。 |
| | | * |
| | | * **Note:**<br> |
| | | * 在 uni-app 中 path 如何获取。 |
| | | * - 使用 cdn 地址,例如:`path = https://web.sdk.qcloud.com/component/TUIKit/assets/uni-app/calling-bell-1.mp3;` |
| | | * - 使用本地绝对路径。 |
| | | * 1. 通过 [uni.saveFile](https://zh.uniapp.dcloud.io/api/file/file.html#savefile) 获取保存后的相对路径(建议这种路径)。 |
| | | * 2. 将上一步的相对路径转成绝对路径,[plus.io.convertLocalFileSystemURL](https://www.html5plus.org/doc/zh_cn/io.html#plus.io.convertLocalFileSystemURL)。 |
| | | * |
| | | * @param {AudioMusicParam} musicParam 音乐参数 |
| | | * @param {Number} musicParam.id 音乐 ID |
| | | * @param {String} musicParam.path 音效文件的完整路径或 URL 地址。支持的音频格式包括 MP3、AAC、M4A、WAV |
| | | * @param {Number} musicParam.loopCount 音乐循环播放的次数。取值范围为0 - 任意正整数,默认值:0。0表示播放音乐一次;1表示播放音乐两次;以此类推 |
| | | * @param {Boolean} musicParam.publish 是否将音乐传到远端。true:音乐在本地播放的同时,远端用户也能听到该音乐;false:主播只能在本地听到该音乐,远端观众听不到。默认值:false。 |
| | | * @param {Boolean} musicParam.isShortFile 播放的是否为短音乐文件。true:需要重复播放的短音乐文件;false:正常的音乐文件。默认值:false |
| | | * @param {Number} musicParam.startTimeMS 音乐开始播放时间点,单位: 毫秒。 |
| | | * @param {Number} musicParam.endTimeMS 音乐结束播放时间点,单位: 毫秒,0 表示播放至文件结尾。 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * import { AudioMusicParam } from '@/TrtcCloud/lib/TrtcDefines'; |
| | | * const musicParam = { |
| | | * id: 1, |
| | | * path: '', |
| | | * loopCount: 1, |
| | | * publish: true, |
| | | * isShortFile: false, |
| | | * startTimeMS: 0, |
| | | * endTimeMS: 0, |
| | | * }; |
| | | * this.trtcCloud.startPlayMusic(musicParam); |
| | | */ |
| | | startPlayMusic(musicParam) { |
| | | return TrtcCloudImpl._getInstance().startPlayMusic(musicParam); |
| | | } |
| | | /** |
| | | * 停止播放背景音乐 |
| | | * @param {Number} id 音乐 ID |
| | | * |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const musicId = 5; |
| | | * this.trtcCloud.stopPlayMusic(musicId); |
| | | */ |
| | | stopPlayMusic(id) { |
| | | return TrtcCloudImpl._getInstance().stopPlayMusic(id); |
| | | } |
| | | /** |
| | | * 暂停播放背景音乐 |
| | | * @param {Number} id 音乐 ID |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const musicId = 5; |
| | | * this.trtcCloud.pausePlayMusic(musicId); |
| | | */ |
| | | pausePlayMusic(id) { |
| | | return TrtcCloudImpl._getInstance().pausePlayMusic(id); |
| | | } |
| | | /** |
| | | * 恢复播放背景音乐 |
| | | * @param {Number} id 音乐 ID |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const musicId = 5; |
| | | * this.trtcCloud.resumePlayMusic(musicId); |
| | | */ |
| | | resumePlayMusic(id) { |
| | | return TrtcCloudImpl._getInstance().resumePlayMusic(id); |
| | | } |
| | | /** |
| | | * 调用实验性接口 |
| | | * @param {any} params 实验性接口参数 |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * this.trtcCloud.callExperimentalAPI(params); |
| | | */ |
| | | callExperimentalAPI(params) { |
| | | return TrtcCloudImpl._getInstance().callExperimentalAPI(params); |
| | | } |
| | | /** |
| | | * 使用 UDP 通道发送自定义消息给房间内所有用户<br> |
| | | * 该接口可以让您借助 TRTC 的 UDP 通道,向当前房间里的其他用户广播自定义数据,以达到传输信令的目的。 |
| | | * 房间中的其他用户可以通过 onRecvCustomCmdMsg 事件接收消息。 |
| | | * |
| | | * **Note:** |
| | | * 1. 发送消息到房间内所有用户(暂时不支持 Web/小程序端),每秒最多能发送30条消息(与 {sendSEIMsg} 共享限制)。 |
| | | * 2. 每个包最大为 1KB,超过则很有可能会被中间路由器或者服务器丢弃。 |
| | | * 3. 每个客户端每秒最多能发送总计 16KB 数据(与 {sendSEIMsg} 共享限制)。 |
| | | * 4. 请将 `reliable` 和 `ordered` 同时设置为 true 或同时设置为 false,暂不支持交叉设置。 |
| | | * 5. 强烈建议您将不同类型的消息设定为不同的 cmdID,这样可以在要求有序的情况下减小消息时延。 |
| | | * |
| | | * @param {any} params - 参数 |
| | | * @param {Number} params.cmdID - 消息 ID,取值范围为 [1, 10] |
| | | * @param {String} params.data - 待发送的消息,单个消息的最大长度被限制为 1KB |
| | | * @param {Boolean} params.reliable - 是否可靠发送,可靠发送可以获得更高的发送成功率,但可靠发送比不可靠发送会带来更大的接收延迟 |
| | | * @param {Number} params.ordered - 是否要求有序,即是否要求接收端的数据包顺序和发送端的数据包顺序一致(这会带来一定的接收延时) |
| | | * @return true:消息已经发出;false:消息发送失败。 |
| | | |
| | | * @memberof TrtcCloud |
| | | * @example |
| | | * const params = { |
| | | * cmdID: 1, |
| | | * data: 'hello world', |
| | | * reliable: true, |
| | | * ordered: true, |
| | | * }; |
| | | * this.trtcCloud.sendCustomCmdMsg(params); |
| | | */ |
| | | sendCustomCmdMsg(params) { |
| | | return TrtcCloudImpl._getInstance().sendCustomCmdMsg(params); |
| | | } |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // 设置 TRTCCallback 回调 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 设置 TrtcCloud 回调 |
| | | * |
| | | * @example |
| | | * // 创建/使用/销毁 TrtcCloud 对象的示例代码: |
| | | * import TrtcCloud from '@/TrtcCloud/lib/index'; |
| | | * this.trtcCloud = new TrtcCloud(); |
| | | * |
| | | * // 添加事件监听的方法,事件关键字详见下方”通用事件回调“ |
| | | * this.trtcCloud.on('onEnterRoom', (result) => { |
| | | * if (result > 0) { |
| | | * console.log(`enter room success, spend ${result}ms`); |
| | | * } else { |
| | | * console.log(`enter room failed, error code = ${result}`); |
| | | * } |
| | | * }); |
| | | * |
| | | * @namespace TRTCCallback |
| | | */ |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | // |
| | | // (一)事件回调 |
| | | // |
| | | ///////////////////////////////////////////////////////////////////////////////// |
| | | /** |
| | | * 错误回调,表示 SDK 不可恢复的错误,一定要监听并分情况给用户适当的界面提示<br> |
| | | * @event TRTCCallback#onError |
| | | * @param {Number} code 错误码,[详见](https://cloud.tencent.com/document/product/647/38308#.E9.94.99.E8.AF.AF.E7.A0.81.E8.A1.A8) |
| | | * @param {String} message 错误信息 |
| | | * @param {Object} extraInfo 扩展信息字段,个别错误码可能会带额外的信息帮助定位问题 |
| | | */ |
| | | onError(code, message, extraInfo) { } |
| | | /** |
| | | * 警告回调,用于告知您一些非严重性问题,例如出现卡顿或者可恢复的解码失败<br> |
| | | * @event TRTCCallback#onWarning |
| | | * @param {Number} code 警告码,[详见](https://cloud.tencent.com/document/product/647/38308#.E8.AD.A6.E5.91.8A.E7.A0.81.E8.A1.A8) |
| | | * @param {String} message 警告信息 |
| | | * @param {Object} extraInfo 扩展信息字段,个别警告码可能会带额外的信息帮助定位问题 |
| | | */ |
| | | onWarning(code, message, extraInfo) { } |
| | | /** |
| | | * 进房后的回调<br> |
| | | * 调用 `enterRoom()` 接口执行进房操作后,会收到 `onEnterRoom(result)` 回调<br> |
| | | * 如果加入成功,result 会是一个正数(result > 0),代表加入房间的时间消耗,单位是毫秒(ms)。<br> |
| | | * 如果加入失败,result 会是一个负数(result < 0),代表进房失败的错误码。 |
| | | * |
| | | * @event TRTCCallback#onEnterRoom |
| | | * @param {Number} result 进房耗时 |
| | | */ |
| | | onEnterRoom(result) { } |
| | | /** |
| | | * 离开房间的事件回调<br> |
| | | * 调用 `exitRoom()` 接口会执行退出房间的相关逻辑,例如释放音视频设备资源和编解码器资源等。待资源释放完毕,会通过 `onExitRoom()` 回调通知到您<br> |
| | | * |
| | | * **Note:** |
| | | * - 如果您要再次调用 `enterRoom()` 或者切换到其他的音视频 SDK,请等待 `onExitRoom()` 回调到来之后再执行相关操作。 否则可能会遇到音频设备被占用等各种异常问题 |
| | | * |
| | | * @event TRTCCallback#onExitRoom |
| | | * @param {Number} reason 离开房间原因,0:主动调用 exitRoom 退房;1:被服务器踢出当前房间;2:当前房间整个被解散 |
| | | */ |
| | | onExitRoom(reason) { } |
| | | /** |
| | | * 跨房通话事件回调<br> |
| | | * 调用 TRTCCloud 中的 [connectOtherRoom()](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TrtcCloud.html#connectOtherRoom) 接口会将两个不同房间中的主播拉通视频通话,也就是所谓的“主播PK”功能。 |
| | | * 调用者会收到 onConnectOtherRoom() 事件回调来获知跨房通话是否成功, 如果成功,两个房间中的所有用户都会收到来自另一个房间中的 PK 主播的 [onUserVideoAvailable()](http://127.0.0.1:5500/UniApp-TRTC-SDK/packages/TrtcCloud/docs/zh-cn/api/TRTCCallback.html#event:onUserVideoAvailable) 回调。 |
| | | * |
| | | * @event TRTCCallback#onConnectOtherRoom |
| | | * @param {Object} params 调用 [connectOtherRoom()](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TrtcCloud.html#connectOtherRoom) 接口返回值数据。 |
| | | * - userId:跨房通话时对端 userId |
| | | * - errCode: [错误状态码](https://cloud.tencent.com/document/product/647/38308#.E8.AD.A6.E5.91.8A.E7.A0.81.E8.A1.A8),返回0表示跨房通话成功。 |
| | | * - errMsg: 状态信息,跨房通话成功返回 OK。 |
| | | */ |
| | | onConnectOtherRoom(params) { } |
| | | /** |
| | | * 结束跨房通话的结果回调<br> |
| | | * 调用 TRTCCloud 中的 [disconnectOtherRoom()](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TrtcCloud.html#disconnectOtherRoom) 接口会将两个不同房间中的主播拉通视频通话,也就是所谓的“主播PK”功能。 |
| | | * 调用者会收到 onDisconnectOtherRoom() 事件回调来获知结束跨房通话是否成功。 |
| | | * |
| | | * @event TRTCCallback#onDisconnectOtherRoom |
| | | * @param {Object} params 调用 [disconnectOtherRoom()](https://web.sdk.qcloud.com/trtc/uniapp/doc/zh-cn/TrtcCloud.html#disconnectOtherRoom) 失败时返回的错误数据。 |
| | | * - errCode: [错误状态码](https://cloud.tencent.com/document/product/647/38308#.E8.AD.A6.E5.91.8A.E7.A0.81.E8.A1.A8)。 |
| | | * - errMsg: 错误信息。 |
| | | */ |
| | | onDisconnectOtherRoom(params) { } |
| | | /** |
| | | * 切换角色的事件回调<br> |
| | | * 调用 TRTCCloud 中的 switchRole() 接口会切换主播和观众的角色,该操作会伴随一个线路切换的过程, 待 SDK 切换完成后,会抛出 onSwitchRole() 事件回调 |
| | | * |
| | | * @event TRTCCallback#onSwitchRole |
| | | * @param {Number} code 错误码,[详见](https://cloud.tencent.com/document/product/647/38308#.E8.AD.A6.E5.91.8A.E7.A0.81.E8.A1.A8) |
| | | * @param {String} message 错误信息 |
| | | */ |
| | | onSwitchRole(code, message) { } |
| | | /** |
| | | * 开始渲染本地或远程用户的首帧画面<br> |
| | | * 如果 userId 为 null,代表开始渲染本地采集的摄像头画面,需要您先调用 `startLocalPreview` 触发。 如果 userId 不为 null,代表开始渲染远程用户的首帧画面,需要您先调用 `startRemoteView` 触发<br> |
| | | * 只有当您调用 `startLocalPreview()、startRemoteView() 或 startRemoteSubStreamView()` 之后,才会触发该回调 |
| | | * |
| | | * @event TRTCCallback#onFirstVideoFrame |
| | | * @param {String} userId 本地或远程用户 ID,如果 userId === null 代表本地,userId !== null 代表远程 |
| | | * @param {Number} streamType 视频流类型:摄像头或屏幕分享 |
| | | * @param {Number} width 画面宽度 |
| | | * @param {Number} height 画面高度 |
| | | */ |
| | | onFirstVideoFrame(userId, streamType, width, height) { } |
| | | /** |
| | | * 开始播放远程用户的首帧音频(本地声音暂不通知)<br> |
| | | * 如果 userId 为 null,代表开始渲染本地采集的摄像头画面,需要您先调用 `startLocalPreview` 触发。 如果 userId 不为 null,代表开始渲染远程用户的首帧画面,需要您先调用 `startRemoteView` 触发<br> |
| | | * 只有当您调用 `startLocalPreview()、startRemoteView() 或 startRemoteSubStreamView()` 之后,才会触发该回调 |
| | | * |
| | | * @event TRTCCallback#onFirstAudioFrame |
| | | * @param {String} userId 远程用户 ID |
| | | */ |
| | | onFirstAudioFrame(userId) { } |
| | | /** |
| | | * 截图完成时回调<br> |
| | | * @event TRTCCallback#onSnapshotComplete |
| | | * @param {String} base64Data 截图对应的 base64 数据 |
| | | * @param {String} message 错误信息 |
| | | */ |
| | | onSnapshotComplete(base64Data, message) { } |
| | | /** |
| | | * 麦克风准备就绪 |
| | | */ |
| | | onMicDidReady() { } |
| | | /** |
| | | * 摄像头准备就绪 |
| | | */ |
| | | onCameraDidReady() { } |
| | | /** |
| | | * 网络质量:该回调每2秒触发一次,统计当前网络的上行和下行质量<br> |
| | | * userId 为本地用户 ID 代表自己当前的视频质量 |
| | | * |
| | | * @param {String} localQuality 上行网络质量 |
| | | * @param {String} remoteQuality 下行网络质量 |
| | | */ |
| | | onNetworkQuality(localQuality, remoteList) { } |
| | | /** |
| | | * 有用户加入当前房间<br> |
| | | * 出于性能方面的考虑,在两种不同的应用场景下,该通知的行为会有差别:<br> |
| | | * 通话场景(TRTCAppScene.TRTCAppSceneVideoCall 和 TRTCAppScene.TRTCAppSceneAudioCall):该场景下用户没有角色的区别,任何用户进入房间都会触发该通知。<br> |
| | | * 直播场景(TRTCAppScene.TRTCAppSceneLIVE 和 TRTCAppScene.TRTCAppSceneVoiceChatRoom ):该场景不限制观众的数量,如果任何用户进出都抛出回调会引起很大的性能损耗,所以该场景下只有主播进入房间时才会触发该通知,观众进入房间不会触发该通知 |
| | | * |
| | | * @event TRTCCallback#onRemoteUserEnterRoom |
| | | * @param {String} userId 用户标识 ID |
| | | */ |
| | | onRemoteUserEnterRoom(userId) { } |
| | | /** |
| | | * 有用户离开当前房间<br> |
| | | * 与 onRemoteUserEnterRoom 相对应,在两种不同的应用场景下,该通知的行为会有差别:<br> |
| | | * 通话场景(TRTCAppScene.TRTCAppSceneVideoCall 和 TRTCAppScene.TRTCAppSceneAudioCall):该场景下用户没有角色的区别,任何用户进入房间都会触发该通知。<br> |
| | | * 直播场景(TRTCAppScene.TRTCAppSceneLIVE 和 TRTCAppScene.TRTCAppSceneVoiceChatRoom ):该场景不限制观众的数量,如果任何用户进出都抛出回调会引起很大的性能损耗,所以该场景下只有主播进入房间时才会触发该通知,观众进入房间不会触发该通知 |
| | | * |
| | | * @event TRTCCallback#onRemoteUserLeaveRoom |
| | | * @param {String} userId 用户标识 ID |
| | | * @param {Number} reason 离开原因,0 表示用户主动退出房间,1 表示用户超时退出,2 表示被踢出房间 |
| | | */ |
| | | onRemoteUserLeaveRoom(userId, reason) { } |
| | | /** |
| | | * 首帧本地音频数据已经被送出<br> |
| | | * 在 `enterRoom()` 并 `startLocalAudio()` 成功后开始麦克风采集,并将采集到的声音进行编码。 当 SDK 成功向云端送出第一帧音频数据后,会抛出这个回调事件 |
| | | * |
| | | * @event TRTCCallback#onSendFirstLocalAudioFrame |
| | | */ |
| | | onSendFirstLocalAudioFrame() { } |
| | | /** |
| | | * 首帧本地视频数据已经被送出<br> |
| | | * SDK 会在 `enterRoom()` 并 `startLocalPreview()` 成功后开始摄像头采集,并将采集到的画面进行编码。 当 SDK 成功向云端送出第一帧视频数据后,会抛出这个回调事件 |
| | | * |
| | | * @event TRTCCallback#onSendFirstLocalVideoFrame |
| | | * @param {Number} streamType 视频流类型,大画面、小画面或辅流画面(屏幕分享) |
| | | */ |
| | | onSendFirstLocalVideoFrame(streamType) { } |
| | | /** |
| | | * 技术指标统计回调<br> |
| | | * 如果您是熟悉音视频领域相关术语,可以通过这个回调获取 SDK 的所有技术指标。 如果您是首次开发音视频相关项目,可以只关注 `onNetworkQuality` 回调 |
| | | * |
| | | * **Note:** |
| | | * - 每 2 秒回调一次 |
| | | * |
| | | * @param {Object} statics 状态数据 |
| | | */ |
| | | onStatistics(statics) { } |
| | | /** |
| | | * 远端用户是否存在可播放的音频数据<br> |
| | | * @event TRTCCallback#onUserAudioAvailable |
| | | * @param {String} userId 用户标识 ID |
| | | * @param {Boolean} available 声音是否开启 |
| | | */ |
| | | onUserAudioAvailable(userId, available) { } |
| | | /** |
| | | * 远端用户是否存在可播放的主路画面(一般用于摄像头)<br> |
| | | * 当您收到 `onUserVideoAvailable(userId, true)` 通知时,表示该路画面已经有可用的视频数据帧到达。 此时,您需要调用 `startRemoteView(userId)` 接口加载该用户的远程画面。 然后,您会收到名为 onFirstVideoFrame(userid) 的首帧画面渲染回调。<br> |
| | | * 当您收到 `onUserVideoAvailable(userId, false)` 通知时,表示该路远程画面已经被关闭,可能由于该用户调用了 `muteLocalVideo()` 或 `stopLocalPreview()`。 |
| | | * |
| | | * @event TRTCCallback#onUserVideoAvailable |
| | | * @param {String} userId 用户标识 ID |
| | | * @param {Boolean} available 画面是否开启 |
| | | */ |
| | | onUserVideoAvailable(userId, available) { } |
| | | /** |
| | | * 用于提示音量大小的回调,包括每个 userId 的音量和远端总音量<br> |
| | | * SDK 可以评估每一路音频的音量大小,并每隔一段时间抛出该事件回调,您可以根据音量大小在 UI 上做出相应的提示,比如“波形图”或“音量槽”。 要完成这个功能, 您需要先调用 enableAudioVolumeEvaluation 开启这个能力并设定事件抛出的时间间隔。 需要补充说明的是,无论当前房间中是否有人说话,SDK 都会按照您设定的时间间隔定时抛出此事件回调,只不过当没有人说话时,userVolumes 为空,totalVolume 为 0。 |
| | | * |
| | | * **Note:** |
| | | * - userVolumes 为一个数组,对于数组中的每一个元素,当 userId 为空时表示本地麦克风采集的音量大小,当 userId 不为空时代表远端用户的音量大小 |
| | | * |
| | | * @event TRTCCallback#onUserVoiceVolume |
| | | * @param {Array} userVolumes 是一个数组,用于承载所有正在说话的用户的音量大小,取值范围 0 - 100 |
| | | * @param {Number} totalVolume 所有远端用户的总音量大小, 取值范围 0 - 100 |
| | | */ |
| | | onUserVoiceVolume(userVolumes, totalVolume) { } |
| | | /** |
| | | * 屏幕分享开启的事件回调<br> |
| | | * 当您通过 startScreenCapture 等相关接口启动屏幕分享时,SDK 便会抛出此事件回调 |
| | | * @event TRTCCallback#onScreenCaptureStarted |
| | | */ |
| | | onScreenCaptureStarted() { } |
| | | /** |
| | | * 屏幕分享停止的事件回调<br> |
| | | * 当您通过 stopScreenCapture 停止屏幕分享时,SDK 便会抛出此事件回调 |
| | | * @event TRTCCallback#onScreenCaptureStopped |
| | | * @param {Number} reason 停止原因,0:用户主动停止;1:屏幕窗口关闭导致停止;2:表示屏幕分享的显示屏状态变更(如接口被拔出、投影模式变更等) |
| | | */ |
| | | onScreenCaptureStopped(reason) { } |
| | | /** |
| | | * 屏幕分享停止的事件回调<br> |
| | | * 当您通过 pauseScreenCapture 停止屏幕分享时,SDK 便会抛出此事件回调 |
| | | * @event TRTCCallback#onScreenCapturePaused |
| | | * @param {Number} reason 停止原因,0:用户主动停止;1:屏幕窗口关闭导致停止;2:表示屏幕分享的显示屏状态变更(如接口被拔出、投影模式变更等) |
| | | */ |
| | | onScreenCapturePaused(reason) { } |
| | | /** |
| | | * 屏幕分享恢复的事件回调<br> |
| | | * 当您通过 resumeScreenCapture 恢复屏幕分享时,SDK 便会抛出此事件回调 |
| | | * @event TRTCCallback#onScreenCaptureResumed |
| | | */ |
| | | onScreenCaptureResumed() { } |
| | | /** |
| | | * 某远端用户发布/取消了辅路视频画面<br> |
| | | * “辅路画面”一般被用于承载屏幕分享的画面。当您收到 onUserSubStreamAvailable(userId, true) 通知时,表示该路画面已经有可播放的视频帧到达。 此时,您需要调用 startRemoteView 接口订阅该用户的远程画面,订阅成功后,您会继续收到该用户的首帧画面渲染回调 onFirstVideoFrame(userId) |
| | | * |
| | | * **Note:** |
| | | * - 拉取 Web 端(用 [WebRTC](https://web.sdk.qcloud.com/trtc/webrtc/doc/zh-cn/index.html) 实现屏幕分享)的屏幕分享,收不到 onUserSubStreamAvailable 事件。因为 [WebRTC](https://web.sdk.qcloud.com/trtc/webrtc/doc/zh-cn/index.html) 推的屏幕分享也是主流 |
| | | * @param {String} userId 用户 ID |
| | | * @param {Boolean} available 是否可用,true 表示辅流可用 |
| | | * @event TRTCCallback#onUserSubStreamAvailable |
| | | */ |
| | | onUserSubStreamAvailable(userId, available) { } |
| | | /** |
| | | * 用户视频大小发生改变回调。<br> |
| | | * 当您收到 onUserVideoSizeChanged(userId, streamtype, newWidth, newHeight) 通知时,表示该路画面大小发生了调整,调整的原因可能是该用户调用了 setVideoEncoderParam 或者 setSubStreamEncoderParam 重新设置了画面尺寸。 |
| | | * @param {String} userId 用户 ID |
| | | * @param {Number} streamType 视频流类型,仅支持 TRTCVideoStreamTypeBig 和 TRTCVideoStreamTypeSub |
| | | * @param {Number} newWidth 视频流的宽度(像素) |
| | | * @param {Number} newHeight 视频流的高度(像素) |
| | | * @event TRTCCallback#onUserVideoSizeChanged |
| | | */ |
| | | onUserVideoSizeChanged(userId, streamType, newWidth, newHeight) { } |
| | | /** |
| | | * 背景音乐开始播放 |
| | | * @param {Number} id 播放的 id |
| | | * @param {Number} errCode 播放的状态码 |
| | | * @event TRTCCallback#onStart |
| | | */ |
| | | onStart(id, errCode) { } |
| | | /** |
| | | * 背景音乐的播放进度 |
| | | * @param {Number} id 播放的 id |
| | | * @param {Number} curPtsMS 当前播放的位置 |
| | | * @param {Number} durationMS 当前音频总时长 |
| | | * @event TRTCCallback#onPlayProgress |
| | | */ |
| | | onPlayProgress(id, curPtsMS, durationMS) { } |
| | | /** |
| | | * 背景音乐已经播放完毕 |
| | | * @param {Number} id 播放的 id |
| | | * @param {Number} errCode 播放结束的状态码 |
| | | * @event TRTCCallback#onComplete |
| | | */ |
| | | onComplete(id, errCode) { } |
| | | /** |
| | | * 收到自定义消息的事件回调。 |
| | | * |
| | | * 当房间中的某个用户使用 {sendCustomCmdMsg} 发送自定义 UDP 消息时,房间中的其他用户可以通过 `onRecvCustomCmdMsg` 事件回调接收到该条消息。 |
| | | * @param {String} userId 用户标识。 |
| | | * @param {Number} cmdID 命令 ID。 |
| | | * @param {Number} seq 消息序号。 |
| | | * @param {String} message 消息数据。 |
| | | * @event TRTCCallback#onRecvCustomCmdMsg |
| | | */ |
| | | onRecvCustomCmdMsg(userId, cmdID, seq, message) { } |
| | | } |
| New file |
| | |
| | | /** |
| | | * 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启 |
| | | */ |
| | | var isIos |
| | | // #ifdef APP-PLUS |
| | | isIos = (plus.os.name == "iOS"); |
| | | // #endif |
| | | |
| | | // 判断推送权限是否开启 |
| | | function judgeIosPermissionPush() { |
| | | var result = false; |
| | | var UIApplication = plus.ios.import("UIApplication"); |
| | | var app = UIApplication.sharedApplication(); |
| | | var enabledTypes = 0; |
| | | if (app.currentUserNotificationSettings) { |
| | | var settings = app.currentUserNotificationSettings(); |
| | | enabledTypes = settings.plusGetAttribute("types"); |
| | | console.log("enabledTypes1:" + enabledTypes); |
| | | if (enabledTypes == 0) { |
| | | console.log("推送权限没有开启"); |
| | | } else { |
| | | result = true; |
| | | console.log("已经开启推送功能!") |
| | | } |
| | | plus.ios.deleteObject(settings); |
| | | } else { |
| | | enabledTypes = app.enabledRemoteNotificationTypes(); |
| | | if (enabledTypes == 0) { |
| | | console.log("推送权限没有开启!"); |
| | | } else { |
| | | result = true; |
| | | console.log("已经开启推送功能!") |
| | | } |
| | | console.log("enabledTypes2:" + enabledTypes); |
| | | } |
| | | plus.ios.deleteObject(app); |
| | | plus.ios.deleteObject(UIApplication); |
| | | return result; |
| | | } |
| | | |
| | | // 判断定位权限是否开启 |
| | | function judgeIosPermissionLocation() { |
| | | var result = false; |
| | | var cllocationManger = plus.ios.import("CLLocationManager"); |
| | | var status = cllocationManger.authorizationStatus(); |
| | | result = (status != 2) |
| | | console.log("定位权限开启:" + result); |
| | | // 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation |
| | | /* var enable = cllocationManger.locationServicesEnabled(); |
| | | var status = cllocationManger.authorizationStatus(); |
| | | console.log("enable:" + enable); |
| | | console.log("status:" + status); |
| | | if (enable && status != 2) { |
| | | result = true; |
| | | console.log("手机定位服务已开启且已授予定位权限"); |
| | | } else { |
| | | console.log("手机系统的定位没有打开或未给予定位权限"); |
| | | } */ |
| | | plus.ios.deleteObject(cllocationManger); |
| | | return result; |
| | | } |
| | | // 判断麦克风权限是否开启 |
| | | function judgeIosPermissionRecord() { |
| | | var result = false; |
| | | var avaudiosession = plus.ios.import("AVAudioSession"); |
| | | var avaudio = avaudiosession.sharedInstance(); |
| | | var permissionStatus = avaudio.recordPermission(); |
| | | console.log("permissionStatus:" + permissionStatus); |
| | | if (permissionStatus == 1684369017 || permissionStatus == 1970168948) { |
| | | console.log("麦克风权限没有开启"); |
| | | } else { |
| | | result = true; |
| | | console.log("麦克风权限已经开启"); |
| | | } |
| | | plus.ios.deleteObject(avaudiosession); |
| | | return result; |
| | | } |
| | | |
| | | // 判断相机权限是否开启 |
| | | function judgeIosPermissionCamera() { |
| | | var result = false; |
| | | var AVCaptureDevice = plus.ios.import("AVCaptureDevice"); |
| | | var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide'); |
| | | console.log("authStatus:" + authStatus); |
| | | if (authStatus == 3) { |
| | | result = true; |
| | | console.log("相机权限已经开启"); |
| | | } else { |
| | | console.log("相机权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(AVCaptureDevice); |
| | | return result; |
| | | } |
| | | |
| | | // 判断相册权限是否开启 |
| | | function judgeIosPermissionPhotoLibrary() { |
| | | var result = false; |
| | | var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary"); |
| | | var authStatus = PHPhotoLibrary.authorizationStatus(); |
| | | console.log("authStatus:" + authStatus); |
| | | if (authStatus == 3) { |
| | | result = true; |
| | | console.log("相册权限已经开启"); |
| | | } else { |
| | | console.log("相册权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(PHPhotoLibrary); |
| | | return result; |
| | | } |
| | | |
| | | // 判断通讯录权限是否开启 |
| | | function judgeIosPermissionContact() { |
| | | var result = false; |
| | | var CNContactStore = plus.ios.import("CNContactStore"); |
| | | var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0); |
| | | if (cnAuthStatus == 3) { |
| | | result = true; |
| | | console.log("通讯录权限已经开启"); |
| | | } else { |
| | | console.log("通讯录权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(CNContactStore); |
| | | return result; |
| | | } |
| | | |
| | | // 判断日历权限是否开启 |
| | | function judgeIosPermissionCalendar() { |
| | | var result = false; |
| | | var EKEventStore = plus.ios.import("EKEventStore"); |
| | | var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0); |
| | | if (ekAuthStatus == 3) { |
| | | result = true; |
| | | console.log("日历权限已经开启"); |
| | | } else { |
| | | console.log("日历权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(EKEventStore); |
| | | return result; |
| | | } |
| | | |
| | | // 判断备忘录权限是否开启 |
| | | function judgeIosPermissionMemo() { |
| | | var result = false; |
| | | var EKEventStore = plus.ios.import("EKEventStore"); |
| | | var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1); |
| | | if (ekAuthStatus == 3) { |
| | | result = true; |
| | | console.log("备忘录权限已经开启"); |
| | | } else { |
| | | console.log("备忘录权限没有开启"); |
| | | } |
| | | plus.ios.deleteObject(EKEventStore); |
| | | return result; |
| | | } |
| | | |
| | | // Android权限查询 |
| | | function requestAndroidPermission(permissionID) { |
| | | return new Promise((resolve, reject) => { |
| | | plus.android.requestPermissions( |
| | | [permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装 |
| | | function(resultObj) { |
| | | var result = 0; |
| | | for (var i = 0; i < resultObj.granted.length; i++) { |
| | | var grantedPermission = resultObj.granted[i]; |
| | | console.log('已获取的权限:' + grantedPermission); |
| | | result = 1 |
| | | } |
| | | for (var i = 0; i < resultObj.deniedPresent.length; i++) { |
| | | var deniedPresentPermission = resultObj.deniedPresent[i]; |
| | | console.log('拒绝本次申请的权限:' + deniedPresentPermission); |
| | | result = 0 |
| | | } |
| | | for (var i = 0; i < resultObj.deniedAlways.length; i++) { |
| | | var deniedAlwaysPermission = resultObj.deniedAlways[i]; |
| | | console.log('永久拒绝申请的权限:' + deniedAlwaysPermission); |
| | | result = -1 |
| | | } |
| | | resolve(result); |
| | | // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限 |
| | | // if (result != 1) { |
| | | // gotoAppPermissionSetting() |
| | | // } |
| | | }, |
| | | function(error) { |
| | | console.log('申请权限错误:' + error.code + " = " + error.message); |
| | | resolve({ |
| | | code: error.code, |
| | | message: error.message |
| | | }); |
| | | } |
| | | ); |
| | | }); |
| | | } |
| | | |
| | | // 使用一个方法,根据参数判断权限 |
| | | function judgeIosPermission(permissionID) { |
| | | if (permissionID == "location") { |
| | | return judgeIosPermissionLocation() |
| | | } else if (permissionID == "camera") { |
| | | return judgeIosPermissionCamera() |
| | | } else if (permissionID == "photoLibrary") { |
| | | return judgeIosPermissionPhotoLibrary() |
| | | } else if (permissionID == "record") { |
| | | return judgeIosPermissionRecord() |
| | | } else if (permissionID == "push") { |
| | | return judgeIosPermissionPush() |
| | | } else if (permissionID == "contact") { |
| | | return judgeIosPermissionContact() |
| | | } else if (permissionID == "calendar") { |
| | | return judgeIosPermissionCalendar() |
| | | } else if (permissionID == "memo") { |
| | | return judgeIosPermissionMemo() |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // 跳转到**应用**的权限页面 |
| | | function gotoAppPermissionSetting() { |
| | | if (isIos) { |
| | | var UIApplication = plus.ios.import("UIApplication"); |
| | | var application2 = UIApplication.sharedApplication(); |
| | | var NSURL2 = plus.ios.import("NSURL"); |
| | | // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES"); |
| | | var setting2 = NSURL2.URLWithString("app-settings:"); |
| | | application2.openURL(setting2); |
| | | |
| | | plus.ios.deleteObject(setting2); |
| | | plus.ios.deleteObject(NSURL2); |
| | | plus.ios.deleteObject(application2); |
| | | } else { |
| | | // console.log(plus.device.vendor); |
| | | var Intent = plus.android.importClass("android.content.Intent"); |
| | | var Settings = plus.android.importClass("android.provider.Settings"); |
| | | var Uri = plus.android.importClass("android.net.Uri"); |
| | | var mainActivity = plus.android.runtimeMainActivity(); |
| | | var intent = new Intent(); |
| | | intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); |
| | | var uri = Uri.fromParts("package", mainActivity.getPackageName(), null); |
| | | intent.setData(uri); |
| | | mainActivity.startActivity(intent); |
| | | } |
| | | } |
| | | |
| | | // 检查系统的设备服务是否开启 |
| | | // var checkSystemEnableLocation = async function () { |
| | | function checkSystemEnableLocation() { |
| | | if (isIos) { |
| | | var result = false; |
| | | var cllocationManger = plus.ios.import("CLLocationManager"); |
| | | var result = cllocationManger.locationServicesEnabled(); |
| | | console.log("系统定位开启:" + result); |
| | | plus.ios.deleteObject(cllocationManger); |
| | | return result; |
| | | } else { |
| | | var context = plus.android.importClass("android.content.Context"); |
| | | var locationManager = plus.android.importClass("android.location.LocationManager"); |
| | | var main = plus.android.runtimeMainActivity(); |
| | | var mainSvr = main.getSystemService(context.LOCATION_SERVICE); |
| | | var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER); |
| | | console.log("系统定位开启:" + result); |
| | | return result |
| | | } |
| | | } |
| | | |
| | | // module.exports = { |
| | | // judgeIosPermission: judgeIosPermission, |
| | | // requestAndroidPermission: requestAndroidPermission, |
| | | // checkSystemEnableLocation: checkSystemEnableLocation, |
| | | // gotoAppPermissionSetting: gotoAppPermissionSetting |
| | | // } |
| | | |
| | | // HBuilder 选择 vue3 时, 上面的打包无法通过 import 进行引入 |
| | | export default { |
| | | judgeIosPermission: judgeIosPermission, |
| | | requestAndroidPermission: requestAndroidPermission, |
| | | checkSystemEnableLocation: checkSystemEnableLocation, |
| | | gotoAppPermissionSetting: gotoAppPermissionSetting |
| | | }; |
| | | |
| New file |
| | |
| | | <template> |
| | | <TRTCCloudUniPlugin-TXLocalViewComponent :viewId="viewId"></TRTCCloudUniPlugin-TXLocalViewComponent> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'TrtcLocalView', |
| | | props: { |
| | | viewId: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | |
| | | </style> |
| New file |
| | |
| | | <template> |
| | | <TRTCCloudUniPlugin-TXRemoteViewComponent :userId="userId" :viewId="viewId"></TRTCCloudUniPlugin-TXRemoteViewComponent> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'TrtcRemoteView', |
| | | props: { |
| | | userId: { |
| | | type: String, |
| | | default: '' |
| | | }, |
| | | viewId: { |
| | | type: String, |
| | | default: '' |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | |
| | | </style> |
| New file |
| | |
| | | // #ifdef APP-PLUS |
| | | import TrtcCloud from '@/utils/voiceCallByTX/TrtcCloud/lib/index'; |
| | | import {TRTCAppScene} from '@/utils/voiceCallByTX/TrtcCloud/lib/TrtcDefines'; |
| | | |
| | | const trtcCloud = TrtcCloud.createInstance(); |
| | | // #endif |
| | | |
| | | // #ifdef H5 |
| | | import TRTC from 'trtc-sdk-v5'; |
| | | |
| | | const trtc = TRTC.create(); |
| | | // #endif |
| | | |
| | | import {genTestUserSig} from "@/utils/voiceCallByTX/GenerateTestUserSig.js"; |
| | | import {sendVoiceCallApi} from "@/api/user/index.js"; |
| | | |
| | | export function enterRoom(payload, userId) { |
| | | const data = JSON.parse(payload.data.data) |
| | | const theOtherPartyId = payload.data.caller_id |
| | | const {userSig, SDKAppID: sdkAppId} = genTestUserSig(userId); |
| | | const params = {sdkAppId, userId, roomId: data.roomId, userSig}; |
| | | // #ifdef APP-PLUS |
| | | trtcCloud.enterRoom(params, TRTCAppScene.TRTCAppSceneVideoCall) |
| | | trtcCloud.startLocalAudio(); |
| | | // #endif |
| | | // #ifdef H5 |
| | | trtc.enterRoom(params) |
| | | trtc.startLocalAudio() |
| | | // #endif |
| | | // demo原因,直接接通来进行验证测试 |
| | | sendVoiceCallApi({ |
| | | caller_id: userId, |
| | | receiver_id: theOtherPartyId, |
| | | data: JSON.stringify({state: '接通', roomId: data.roomId}), |
| | | }) |
| | | } |
| New file |
| | |
| | | /*eslint-disable*/ |
| | | var e="undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{},t=[],r=[],n="undefined"!=typeof Uint8Array?Uint8Array:Array,i=!1;function o(){i=!0;for(var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=0,o=e.length;n<o;++n)t[n]=e[n],r[e.charCodeAt(n)]=n;r["-".charCodeAt(0)]=62,r["_".charCodeAt(0)]=63}function a(e,r,n){for(var i,o,a=[],s=r;s<n;s+=3)i=(e[s]<<16)+(e[s+1]<<8)+e[s+2],a.push(t[(o=i)>>18&63]+t[o>>12&63]+t[o>>6&63]+t[63&o]);return a.join("")}function s(e){var r;i||o();for(var n=e.length,s=n%3,h="",l=[],f=0,c=n-s;f<c;f+=16383)l.push(a(e,f,f+16383>c?c:f+16383));return 1===s?(r=e[n-1],h+=t[r>>2],h+=t[r<<4&63],h+="=="):2===s&&(r=(e[n-2]<<8)+e[n-1],h+=t[r>>10],h+=t[r>>4&63],h+=t[r<<2&63],h+="="),l.push(h),l.join("")}function h(e,t,r,n,i){var o,a,s=8*i-n-1,h=(1<<s)-1,l=h>>1,f=-7,c=r?i-1:0,u=r?-1:1,d=e[t+c];for(c+=u,o=d&(1<<-f)-1,d>>=-f,f+=s;f>0;o=256*o+e[t+c],c+=u,f-=8);for(a=o&(1<<-f)-1,o>>=-f,f+=n;f>0;a=256*a+e[t+c],c+=u,f-=8);if(0===o)o=1-l;else{if(o===h)return a?NaN:1/0*(d?-1:1);a+=Math.pow(2,n),o-=l}return(d?-1:1)*a*Math.pow(2,o-n)}function l(e,t,r,n,i,o){var a,s,h,l=8*o-i-1,f=(1<<l)-1,c=f>>1,u=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,d=n?0:o-1,p=n?1:-1,_=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(s=isNaN(t)?1:0,a=f):(a=Math.floor(Math.log(t)/Math.LN2),t*(h=Math.pow(2,-a))<1&&(a--,h*=2),(t+=a+c>=1?u/h:u*Math.pow(2,1-c))*h>=2&&(a++,h/=2),a+c>=f?(s=0,a=f):a+c>=1?(s=(t*h-1)*Math.pow(2,i),a+=c):(s=t*Math.pow(2,c-1)*Math.pow(2,i),a=0));i>=8;e[r+d]=255&s,d+=p,s/=256,i-=8);for(a=a<<i|s,l+=i;l>0;e[r+d]=255&a,d+=p,a/=256,l-=8);e[r+d-p]|=128*_}var f={}.toString,c=Array.isArray||function(e){return"[object Array]"==f.call(e)};function u(){return p.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function d(e,t){if(u()<t)throw new RangeError("Invalid typed array length");return p.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=p.prototype:(null===e&&(e=new p(t)),e.length=t),e}function p(e,t,r){if(!(p.TYPED_ARRAY_SUPPORT||this instanceof p))return new p(e,t,r);if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return v(this,e)}return _(this,e,t,r)}function _(e,t,r,n){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,r,n){if(t.byteLength,r<0||t.byteLength<r)throw new RangeError("'offset' is out of bounds");if(t.byteLength<r+(n||0))throw new RangeError("'length' is out of bounds");t=void 0===r&&void 0===n?new Uint8Array(t):void 0===n?new Uint8Array(t,r):new Uint8Array(t,r,n);p.TYPED_ARRAY_SUPPORT?(e=t).__proto__=p.prototype:e=w(e,t);return e}(e,t,r,n):"string"==typeof t?function(e,t,r){"string"==typeof r&&""!==r||(r="utf8");if(!p.isEncoding(r))throw new TypeError('"encoding" must be a valid string encoding');var n=0|m(t,r),i=(e=d(e,n)).write(t,r);i!==n&&(e=e.slice(0,i));return e}(e,t,r):function(e,t){if(y(t)){var r=0|b(t.length);return 0===(e=d(e,r)).length?e:(t.copy(e,0,0,r),e)}if(t){if("undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return"number"!=typeof t.length||(n=t.length)!=n?d(e,0):w(e,t);if("Buffer"===t.type&&c(t.data))return w(e,t.data)}var n;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(e,t)}function g(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function v(e,t){if(g(t),e=d(e,t<0?0:0|b(t)),!p.TYPED_ARRAY_SUPPORT)for(var r=0;r<t;++r)e[r]=0;return e}function w(e,t){var r=t.length<0?0:0|b(t.length);e=d(e,r);for(var n=0;n<r;n+=1)e[n]=255&t[n];return e}function b(e){if(e>=u())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+u().toString(16)+" bytes");return 0|e}function y(e){return!(null==e||!e._isBuffer)}function m(e,t){if(y(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var r=e.length;if(0===r)return 0;for(var n=!1;;)switch(t){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return q(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return V(e).length;default:if(n)return q(e).length;t=(""+t).toLowerCase(),n=!0}}function k(e,t,r){var n=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return O(this,t,r);case"utf8":case"utf-8":return C(this,t,r);case"ascii":return I(this,t,r);case"latin1":case"binary":return P(this,t,r);case"base64":return M(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return U(this,t,r);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}}function E(e,t,r){var n=e[t];e[t]=e[r],e[r]=n}function S(e,t,r,n,i){if(0===e.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),r=+r,isNaN(r)&&(r=i?0:e.length-1),r<0&&(r=e.length+r),r>=e.length){if(i)return-1;r=e.length-1}else if(r<0){if(!i)return-1;r=0}if("string"==typeof t&&(t=p.from(t,n)),y(t))return 0===t.length?-1:x(e,t,r,n,i);if("number"==typeof t)return t&=255,p.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(e,t,r):Uint8Array.prototype.lastIndexOf.call(e,t,r):x(e,[t],r,n,i);throw new TypeError("val must be string, number or Buffer")}function x(e,t,r,n,i){var o,a=1,s=e.length,h=t.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(e.length<2||t.length<2)return-1;a=2,s/=2,h/=2,r/=2}function l(e,t){return 1===a?e[t]:e.readUInt16BE(t*a)}if(i){var f=-1;for(o=r;o<s;o++)if(l(e,o)===l(t,-1===f?0:o-f)){if(-1===f&&(f=o),o-f+1===h)return f*a}else-1!==f&&(o-=o-f),f=-1}else for(r+h>s&&(r=s-h),o=r;o>=0;o--){for(var c=!0,u=0;u<h;u++)if(l(e,o+u)!==l(t,u)){c=!1;break}if(c)return o}return-1}function R(e,t,r,n){r=Number(r)||0;var i=e.length-r;n?(n=Number(n))>i&&(n=i):n=i;var o=t.length;if(o%2!=0)throw new TypeError("Invalid hex string");n>o/2&&(n=o/2);for(var a=0;a<n;++a){var s=parseInt(t.substr(2*a,2),16);if(isNaN(s))return a;e[r+a]=s}return a}function A(e,t,r,n){return G(q(t,e.length-r),e,r,n)}function B(e,t,r,n){return G(function(e){for(var t=[],r=0;r<e.length;++r)t.push(255&e.charCodeAt(r));return t}(t),e,r,n)}function z(e,t,r,n){return B(e,t,r,n)}function L(e,t,r,n){return G(V(t),e,r,n)}function T(e,t,r,n){return G(function(e,t){for(var r,n,i,o=[],a=0;a<e.length&&!((t-=2)<0);++a)r=e.charCodeAt(a),n=r>>8,i=r%256,o.push(i),o.push(n);return o}(t,e.length-r),e,r,n)}function M(e,t,r){return 0===t&&r===e.length?s(e):s(e.slice(t,r))}function C(e,t,r){r=Math.min(e.length,r);for(var n=[],i=t;i<r;){var o,a,s,h,l=e[i],f=null,c=l>239?4:l>223?3:l>191?2:1;if(i+c<=r)switch(c){case 1:l<128&&(f=l);break;case 2:128==(192&(o=e[i+1]))&&(h=(31&l)<<6|63&o)>127&&(f=h);break;case 3:o=e[i+1],a=e[i+2],128==(192&o)&&128==(192&a)&&(h=(15&l)<<12|(63&o)<<6|63&a)>2047&&(h<55296||h>57343)&&(f=h);break;case 4:o=e[i+1],a=e[i+2],s=e[i+3],128==(192&o)&&128==(192&a)&&128==(192&s)&&(h=(15&l)<<18|(63&o)<<12|(63&a)<<6|63&s)>65535&&h<1114112&&(f=h)}null===f?(f=65533,c=1):f>65535&&(f-=65536,n.push(f>>>10&1023|55296),f=56320|1023&f),n.push(f),i+=c}return function(e){var t=e.length;if(t<=D)return String.fromCharCode.apply(String,e);var r="",n=0;for(;n<t;)r+=String.fromCharCode.apply(String,e.slice(n,n+=D));return r}(n)}p.TYPED_ARRAY_SUPPORT=void 0===e.TYPED_ARRAY_SUPPORT||e.TYPED_ARRAY_SUPPORT,p.poolSize=8192,p._augment=function(e){return e.__proto__=p.prototype,e},p.from=function(e,t,r){return _(null,e,t,r)},p.TYPED_ARRAY_SUPPORT&&(p.prototype.__proto__=Uint8Array.prototype,p.__proto__=Uint8Array),p.alloc=function(e,t,r){return function(e,t,r,n){return g(t),t<=0?d(e,t):void 0!==r?"string"==typeof n?d(e,t).fill(r,n):d(e,t).fill(r):d(e,t)}(null,e,t,r)},p.allocUnsafe=function(e){return v(null,e)},p.allocUnsafeSlow=function(e){return v(null,e)},p.isBuffer=$,p.compare=function(e,t){if(!y(e)||!y(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var r=e.length,n=t.length,i=0,o=Math.min(r,n);i<o;++i)if(e[i]!==t[i]){r=e[i],n=t[i];break}return r<n?-1:n<r?1:0},p.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},p.concat=function(e,t){if(!c(e))throw new TypeError('"list" argument must be an Array of Buffers');if(0===e.length)return p.alloc(0);var r;if(void 0===t)for(t=0,r=0;r<e.length;++r)t+=e[r].length;var n=p.allocUnsafe(t),i=0;for(r=0;r<e.length;++r){var o=e[r];if(!y(o))throw new TypeError('"list" argument must be an Array of Buffers');o.copy(n,i),i+=o.length}return n},p.byteLength=m,p.prototype._isBuffer=!0,p.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var t=0;t<e;t+=2)E(this,t,t+1);return this},p.prototype.swap32=function(){var e=this.length;if(e%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var t=0;t<e;t+=4)E(this,t,t+3),E(this,t+1,t+2);return this},p.prototype.swap64=function(){var e=this.length;if(e%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var t=0;t<e;t+=8)E(this,t,t+7),E(this,t+1,t+6),E(this,t+2,t+5),E(this,t+3,t+4);return this},p.prototype.toString=function(){var e=0|this.length;return 0===e?"":0===arguments.length?C(this,0,e):k.apply(this,arguments)},p.prototype.equals=function(e){if(!y(e))throw new TypeError("Argument must be a Buffer");return this===e||0===p.compare(this,e)},p.prototype.inspect=function(){var e="";return this.length>0&&(e=this.toString("hex",0,50).match(/.{2}/g).join(" "),this.length>50&&(e+=" ... ")),"<Buffer "+e+">"},p.prototype.compare=function(e,t,r,n,i){if(!y(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===r&&(r=e?e.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),t<0||r>e.length||n<0||i>this.length)throw new RangeError("out of range index");if(n>=i&&t>=r)return 0;if(n>=i)return-1;if(t>=r)return 1;if(this===e)return 0;for(var o=(i>>>=0)-(n>>>=0),a=(r>>>=0)-(t>>>=0),s=Math.min(o,a),h=this.slice(n,i),l=e.slice(t,r),f=0;f<s;++f)if(h[f]!==l[f]){o=h[f],a=l[f];break}return o<a?-1:a<o?1:0},p.prototype.includes=function(e,t,r){return-1!==this.indexOf(e,t,r)},p.prototype.indexOf=function(e,t,r){return S(this,e,t,r,!0)},p.prototype.lastIndexOf=function(e,t,r){return S(this,e,t,r,!1)},p.prototype.write=function(e,t,r,n){if(void 0===t)n="utf8",r=this.length,t=0;else if(void 0===r&&"string"==typeof t)n=t,r=this.length,t=0;else{if(!isFinite(t))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");t|=0,isFinite(r)?(r|=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}var i=this.length-t;if((void 0===r||r>i)&&(r=i),e.length>0&&(r<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var o=!1;;)switch(n){case"hex":return R(this,e,t,r);case"utf8":case"utf-8":return A(this,e,t,r);case"ascii":return B(this,e,t,r);case"latin1":case"binary":return z(this,e,t,r);case"base64":return L(this,e,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return T(this,e,t,r);default:if(o)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),o=!0}},p.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var D=4096;function I(e,t,r){var n="";r=Math.min(e.length,r);for(var i=t;i<r;++i)n+=String.fromCharCode(127&e[i]);return n}function P(e,t,r){var n="";r=Math.min(e.length,r);for(var i=t;i<r;++i)n+=String.fromCharCode(e[i]);return n}function O(e,t,r){var n=e.length;(!t||t<0)&&(t=0),(!r||r<0||r>n)&&(r=n);for(var i="",o=t;o<r;++o)i+=X(e[o]);return i}function U(e,t,r){for(var n=e.slice(t,r),i="",o=0;o<n.length;o+=2)i+=String.fromCharCode(n[o]+256*n[o+1]);return i}function H(e,t,r){if(e%1!=0||e<0)throw new RangeError("offset is not uint");if(e+t>r)throw new RangeError("Trying to access beyond buffer length")}function F(e,t,r,n,i,o){if(!y(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>i||t<o)throw new RangeError('"value" argument is out of bounds');if(r+n>e.length)throw new RangeError("Index out of range")}function N(e,t,r,n){t<0&&(t=65535+t+1);for(var i=0,o=Math.min(e.length-r,2);i<o;++i)e[r+i]=(t&255<<8*(n?i:1-i))>>>8*(n?i:1-i)}function Z(e,t,r,n){t<0&&(t=4294967295+t+1);for(var i=0,o=Math.min(e.length-r,4);i<o;++i)e[r+i]=t>>>8*(n?i:3-i)&255}function j(e,t,r,n,i,o){if(r+n>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function W(e,t,r,n,i){return i||j(e,0,r,4),l(e,t,r,n,23,4),r+4}function Y(e,t,r,n,i){return i||j(e,0,r,8),l(e,t,r,n,52,8),r+8}p.prototype.slice=function(e,t){var r,n=this.length;if((e=~~e)<0?(e+=n)<0&&(e=0):e>n&&(e=n),(t=void 0===t?n:~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),t<e&&(t=e),p.TYPED_ARRAY_SUPPORT)(r=this.subarray(e,t)).__proto__=p.prototype;else{var i=t-e;r=new p(i,void 0);for(var o=0;o<i;++o)r[o]=this[o+e]}return r},p.prototype.readUIntLE=function(e,t,r){e|=0,t|=0,r||H(e,t,this.length);for(var n=this[e],i=1,o=0;++o<t&&(i*=256);)n+=this[e+o]*i;return n},p.prototype.readUIntBE=function(e,t,r){e|=0,t|=0,r||H(e,t,this.length);for(var n=this[e+--t],i=1;t>0&&(i*=256);)n+=this[e+--t]*i;return n},p.prototype.readUInt8=function(e,t){return t||H(e,1,this.length),this[e]},p.prototype.readUInt16LE=function(e,t){return t||H(e,2,this.length),this[e]|this[e+1]<<8},p.prototype.readUInt16BE=function(e,t){return t||H(e,2,this.length),this[e]<<8|this[e+1]},p.prototype.readUInt32LE=function(e,t){return t||H(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},p.prototype.readUInt32BE=function(e,t){return t||H(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},p.prototype.readIntLE=function(e,t,r){e|=0,t|=0,r||H(e,t,this.length);for(var n=this[e],i=1,o=0;++o<t&&(i*=256);)n+=this[e+o]*i;return n>=(i*=128)&&(n-=Math.pow(2,8*t)),n},p.prototype.readIntBE=function(e,t,r){e|=0,t|=0,r||H(e,t,this.length);for(var n=t,i=1,o=this[e+--n];n>0&&(i*=256);)o+=this[e+--n]*i;return o>=(i*=128)&&(o-=Math.pow(2,8*t)),o},p.prototype.readInt8=function(e,t){return t||H(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},p.prototype.readInt16LE=function(e,t){t||H(e,2,this.length);var r=this[e]|this[e+1]<<8;return 32768&r?4294901760|r:r},p.prototype.readInt16BE=function(e,t){t||H(e,2,this.length);var r=this[e+1]|this[e]<<8;return 32768&r?4294901760|r:r},p.prototype.readInt32LE=function(e,t){return t||H(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},p.prototype.readInt32BE=function(e,t){return t||H(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},p.prototype.readFloatLE=function(e,t){return t||H(e,4,this.length),h(this,e,!0,23,4)},p.prototype.readFloatBE=function(e,t){return t||H(e,4,this.length),h(this,e,!1,23,4)},p.prototype.readDoubleLE=function(e,t){return t||H(e,8,this.length),h(this,e,!0,52,8)},p.prototype.readDoubleBE=function(e,t){return t||H(e,8,this.length),h(this,e,!1,52,8)},p.prototype.writeUIntLE=function(e,t,r,n){(e=+e,t|=0,r|=0,n)||F(this,e,t,r,Math.pow(2,8*r)-1,0);var i=1,o=0;for(this[t]=255&e;++o<r&&(i*=256);)this[t+o]=e/i&255;return t+r},p.prototype.writeUIntBE=function(e,t,r,n){(e=+e,t|=0,r|=0,n)||F(this,e,t,r,Math.pow(2,8*r)-1,0);var i=r-1,o=1;for(this[t+i]=255&e;--i>=0&&(o*=256);)this[t+i]=e/o&255;return t+r},p.prototype.writeUInt8=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,1,255,0),p.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},p.prototype.writeUInt16LE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,2,65535,0),p.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},p.prototype.writeUInt16BE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,2,65535,0),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},p.prototype.writeUInt32LE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,4,4294967295,0),p.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):Z(this,e,t,!0),t+4},p.prototype.writeUInt32BE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,4,4294967295,0),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):Z(this,e,t,!1),t+4},p.prototype.writeIntLE=function(e,t,r,n){if(e=+e,t|=0,!n){var i=Math.pow(2,8*r-1);F(this,e,t,r,i-1,-i)}var o=0,a=1,s=0;for(this[t]=255&e;++o<r&&(a*=256);)e<0&&0===s&&0!==this[t+o-1]&&(s=1),this[t+o]=(e/a>>0)-s&255;return t+r},p.prototype.writeIntBE=function(e,t,r,n){if(e=+e,t|=0,!n){var i=Math.pow(2,8*r-1);F(this,e,t,r,i-1,-i)}var o=r-1,a=1,s=0;for(this[t+o]=255&e;--o>=0&&(a*=256);)e<0&&0===s&&0!==this[t+o+1]&&(s=1),this[t+o]=(e/a>>0)-s&255;return t+r},p.prototype.writeInt8=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,1,127,-128),p.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},p.prototype.writeInt16LE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,2,32767,-32768),p.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},p.prototype.writeInt16BE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,2,32767,-32768),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},p.prototype.writeInt32LE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,4,2147483647,-2147483648),p.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):Z(this,e,t,!0),t+4},p.prototype.writeInt32BE=function(e,t,r){return e=+e,t|=0,r||F(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),p.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):Z(this,e,t,!1),t+4},p.prototype.writeFloatLE=function(e,t,r){return W(this,e,t,!0,r)},p.prototype.writeFloatBE=function(e,t,r){return W(this,e,t,!1,r)},p.prototype.writeDoubleLE=function(e,t,r){return Y(this,e,t,!0,r)},p.prototype.writeDoubleBE=function(e,t,r){return Y(this,e,t,!1,r)},p.prototype.copy=function(e,t,r,n){if(r||(r=0),n||0===n||(n=this.length),t>=e.length&&(t=e.length),t||(t=0),n>0&&n<r&&(n=r),n===r)return 0;if(0===e.length||0===this.length)return 0;if(t<0)throw new RangeError("targetStart out of bounds");if(r<0||r>=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),e.length-t<n-r&&(n=e.length-t+r);var i,o=n-r;if(this===e&&r<t&&t<n)for(i=o-1;i>=0;--i)e[i+t]=this[i+r];else if(o<1e3||!p.TYPED_ARRAY_SUPPORT)for(i=0;i<o;++i)e[i+t]=this[i+r];else Uint8Array.prototype.set.call(e,this.subarray(r,r+o),t);return o},p.prototype.fill=function(e,t,r,n){if("string"==typeof e){if("string"==typeof t?(n=t,t=0,r=this.length):"string"==typeof r&&(n=r,r=this.length),1===e.length){var i=e.charCodeAt(0);i<256&&(e=i)}if(void 0!==n&&"string"!=typeof n)throw new TypeError("encoding must be a string");if("string"==typeof n&&!p.isEncoding(n))throw new TypeError("Unknown encoding: "+n)}else"number"==typeof e&&(e&=255);if(t<0||this.length<t||this.length<r)throw new RangeError("Out of range index");if(r<=t)return this;var o;if(t>>>=0,r=void 0===r?this.length:r>>>0,e||(e=0),"number"==typeof e)for(o=t;o<r;++o)this[o]=e;else{var a=y(e)?e:q(new p(e,n).toString()),s=a.length;for(o=0;o<r-t;++o)this[o+t]=a[o%s]}return this};var K=/[^+\/0-9A-Za-z-_]/g;function X(e){return e<16?"0"+e.toString(16):e.toString(16)}function q(e,t){var r;t=t||1/0;for(var n=e.length,i=null,o=[],a=0;a<n;++a){if((r=e.charCodeAt(a))>55295&&r<57344){if(!i){if(r>56319){(t-=3)>-1&&o.push(239,191,189);continue}if(a+1===n){(t-=3)>-1&&o.push(239,191,189);continue}i=r;continue}if(r<56320){(t-=3)>-1&&o.push(239,191,189),i=r;continue}r=65536+(i-55296<<10|r-56320)}else i&&(t-=3)>-1&&o.push(239,191,189);if(i=null,r<128){if((t-=1)<0)break;o.push(r)}else if(r<2048){if((t-=2)<0)break;o.push(r>>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;o.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return o}function V(e){return function(e){var t,a,s,h,l,f;i||o();var c=e.length;if(c%4>0)throw new Error("Invalid string. Length must be a multiple of 4");l="="===e[c-2]?2:"="===e[c-1]?1:0,f=new n(3*c/4-l),s=l>0?c-4:c;var u=0;for(t=0,a=0;t<s;t+=4,a+=3)h=r[e.charCodeAt(t)]<<18|r[e.charCodeAt(t+1)]<<12|r[e.charCodeAt(t+2)]<<6|r[e.charCodeAt(t+3)],f[u++]=h>>16&255,f[u++]=h>>8&255,f[u++]=255&h;return 2===l?(h=r[e.charCodeAt(t)]<<2|r[e.charCodeAt(t+1)]>>4,f[u++]=255&h):1===l&&(h=r[e.charCodeAt(t)]<<10|r[e.charCodeAt(t+1)]<<4|r[e.charCodeAt(t+2)]>>2,f[u++]=h>>8&255,f[u++]=255&h),f}(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(K,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function G(e,t,r,n){for(var i=0;i<n&&!(i+r>=t.length||i>=e.length);++i)t[i+r]=e[i];return i}function $(e){return null!=e&&(!!e._isBuffer||J(e)||function(e){return"function"==typeof e.readFloatLE&&"function"==typeof e.slice&&J(e.slice(0,0))}(e))}function J(e){return!!e.constructor&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function Q(e,t){return e(t={exports:{}},t.exports),t.exports}var ee=Q(function(e,t){var r;e.exports=(r=r||function(e,t){var r=Object.create||function(){function e(){}return function(t){var r;return e.prototype=t,r=new e,e.prototype=null,r}}(),n={},i=n.lib={},o=i.Base={extend:function(e){var t=r(this);return e&&t.mixIn(e),t.hasOwnProperty("init")&&this.init!==t.init||(t.init=function(){t.$super.init.apply(this,arguments)}),t.init.prototype=t,t.$super=this,t},create:function(){var e=this.extend();return e.init.apply(e,arguments),e},init:function(){},mixIn:function(e){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);e.hasOwnProperty("toString")&&(this.toString=e.toString)},clone:function(){return this.init.prototype.extend(this)}},a=i.WordArray=o.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:4*e.length},toString:function(e){return(e||h).stringify(this)},concat:function(e){var t=this.words,r=e.words,n=this.sigBytes,i=e.sigBytes;if(this.clamp(),n%4)for(var o=0;o<i;o++){var a=r[o>>>2]>>>24-o%4*8&255;t[n+o>>>2]|=a<<24-(n+o)%4*8}else for(var o=0;o<i;o+=4)t[n+o>>>2]=r[o>>>2];return this.sigBytes+=i,this},clamp:function(){var t=this.words,r=this.sigBytes;t[r>>>2]&=4294967295<<32-r%4*8,t.length=e.ceil(r/4)},clone:function(){var e=o.clone.call(this);return e.words=this.words.slice(0),e},random:function(t){for(var r,n=[],i=function(t){var t=t,r=987654321,n=4294967295;return function(){var i=((r=36969*(65535&r)+(r>>16)&n)<<16)+(t=18e3*(65535&t)+(t>>16)&n)&n;return i/=4294967296,(i+=.5)*(e.random()>.5?1:-1)}},o=0;o<t;o+=4){var s=i(4294967296*(r||e.random()));r=987654071*s(),n.push(4294967296*s()|0)}return new a.init(n,t)}}),s=n.enc={},h=s.Hex={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i<r;i++){var o=t[i>>>2]>>>24-i%4*8&255;n.push((o>>>4).toString(16)),n.push((15&o).toString(16))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n<t;n+=2)r[n>>>3]|=parseInt(e.substr(n,2),16)<<24-n%8*4;return new a.init(r,t/2)}},l=s.Latin1={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i<r;i++){var o=t[i>>>2]>>>24-i%4*8&255;n.push(String.fromCharCode(o))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n<t;n++)r[n>>>2]|=(255&e.charCodeAt(n))<<24-n%4*8;return new a.init(r,t)}},f=s.Utf8={stringify:function(e){try{return decodeURIComponent(escape(l.stringify(e)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(e){return l.parse(unescape(encodeURIComponent(e)))}},c=i.BufferedBlockAlgorithm=o.extend({reset:function(){this._data=new a.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=f.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(t){var r=this._data,n=r.words,i=r.sigBytes,o=this.blockSize,s=4*o,h=i/s,l=(h=t?e.ceil(h):e.max((0|h)-this._minBufferSize,0))*o,f=e.min(4*l,i);if(l){for(var c=0;c<l;c+=o)this._doProcessBlock(n,c);var u=n.splice(0,l);r.sigBytes-=f}return new a.init(u,f)},clone:function(){var e=o.clone.call(this);return e._data=this._data.clone(),e},_minBufferSize:0}),u=(i.Hasher=c.extend({cfg:o.extend(),init:function(e){this.cfg=this.cfg.extend(e),this.reset()},reset:function(){c.reset.call(this),this._doReset()},update:function(e){return this._append(e),this._process(),this},finalize:function(e){e&&this._append(e);var t=this._doFinalize();return t},blockSize:16,_createHelper:function(e){return function(t,r){return new e.init(r).finalize(t)}},_createHmacHelper:function(e){return function(t,r){return new u.HMAC.init(e,r).finalize(t)}}}),n.algo={});return n}(Math),r)}),te=(Q(function(e,t){var r,n,i,o,a,s;e.exports=(i=(n=r=ee).lib,o=i.Base,a=i.WordArray,(s=n.x64={}).Word=o.extend({init:function(e,t){this.high=e,this.low=t}}),s.WordArray=o.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:8*e.length},toX32:function(){for(var e=this.words,t=e.length,r=[],n=0;n<t;n++){var i=e[n];r.push(i.high),r.push(i.low)}return a.create(r,this.sigBytes)},clone:function(){for(var e=o.clone.call(this),t=e.words=this.words.slice(0),r=t.length,n=0;n<r;n++)t[n]=t[n].clone();return e}}),r)}),Q(function(e,t){var r;e.exports=(r=ee,function(){if("function"==typeof ArrayBuffer){var e=r.lib.WordArray,t=e.init;(e.init=function(e){if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),(e instanceof Int8Array||"undefined"!=typeof Uint8ClampedArray&&e instanceof Uint8ClampedArray||e instanceof Int16Array||e instanceof Uint16Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Float32Array||e instanceof Float64Array)&&(e=new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),e instanceof Uint8Array){for(var r=e.byteLength,n=[],i=0;i<r;i++)n[i>>>2]|=e[i]<<24-i%4*8;t.call(this,n,r)}else t.apply(this,arguments)}).prototype=e}}(),r.lib.WordArray)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.WordArray,n=e.enc;function i(e){return e<<8&4278255360|e>>>8&16711935}n.Utf16=n.Utf16BE={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i<r;i+=2){var o=t[i>>>2]>>>16-i%4*8&65535;n.push(String.fromCharCode(o))}return n.join("")},parse:function(e){for(var r=e.length,n=[],i=0;i<r;i++)n[i>>>1]|=e.charCodeAt(i)<<16-i%2*16;return t.create(n,2*r)}},n.Utf16LE={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],o=0;o<r;o+=2){var a=i(t[o>>>2]>>>16-o%4*8&65535);n.push(String.fromCharCode(a))}return n.join("")},parse:function(e){for(var r=e.length,n=[],o=0;o<r;o++)n[o>>>1]|=i(e.charCodeAt(o)<<16-o%2*16);return t.create(n,2*r)}}}(),r.enc.Utf16)}),Q(function(e,t){var r,n,i;e.exports=(i=(n=r=ee).lib.WordArray,n.enc.Base64={stringify:function(e){var t=e.words,r=e.sigBytes,n=this._map;e.clamp();for(var i=[],o=0;o<r;o+=3)for(var a=(t[o>>>2]>>>24-o%4*8&255)<<16|(t[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|t[o+2>>>2]>>>24-(o+2)%4*8&255,s=0;s<4&&o+.75*s<r;s++)i.push(n.charAt(a>>>6*(3-s)&63));var h=n.charAt(64);if(h)for(;i.length%4;)i.push(h);return i.join("")},parse:function(e){var t=e.length,r=this._map,n=this._reverseMap;if(!n){n=this._reverseMap=[];for(var o=0;o<r.length;o++)n[r.charCodeAt(o)]=o}var a=r.charAt(64);if(a){var s=e.indexOf(a);-1!==s&&(t=s)}return function(e,t,r){for(var n=[],o=0,a=0;a<t;a++)if(a%4){var s=r[e.charCodeAt(a-1)]<<a%4*2,h=r[e.charCodeAt(a)]>>>6-a%4*2;n[o>>>2]|=(s|h)<<24-o%4*8,o++}return i.create(n,o)}(e,t,n)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},r.enc.Base64)}),Q(function(e,t){var r;e.exports=(r=ee,function(e){var t=r,n=t.lib,i=n.WordArray,o=n.Hasher,a=t.algo,s=[];!function(){for(var t=0;t<64;t++)s[t]=4294967296*e.abs(e.sin(t+1))|0}();var h=a.MD5=o.extend({_doReset:function(){this._hash=new i.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(e,t){for(var r=0;r<16;r++){var n=t+r,i=e[n];e[n]=16711935&(i<<8|i>>>24)|4278255360&(i<<24|i>>>8)}var o=this._hash.words,a=e[t+0],h=e[t+1],d=e[t+2],p=e[t+3],_=e[t+4],g=e[t+5],v=e[t+6],w=e[t+7],b=e[t+8],y=e[t+9],m=e[t+10],k=e[t+11],E=e[t+12],S=e[t+13],x=e[t+14],R=e[t+15],A=o[0],B=o[1],z=o[2],L=o[3];A=l(A,B,z,L,a,7,s[0]),L=l(L,A,B,z,h,12,s[1]),z=l(z,L,A,B,d,17,s[2]),B=l(B,z,L,A,p,22,s[3]),A=l(A,B,z,L,_,7,s[4]),L=l(L,A,B,z,g,12,s[5]),z=l(z,L,A,B,v,17,s[6]),B=l(B,z,L,A,w,22,s[7]),A=l(A,B,z,L,b,7,s[8]),L=l(L,A,B,z,y,12,s[9]),z=l(z,L,A,B,m,17,s[10]),B=l(B,z,L,A,k,22,s[11]),A=l(A,B,z,L,E,7,s[12]),L=l(L,A,B,z,S,12,s[13]),z=l(z,L,A,B,x,17,s[14]),A=f(A,B=l(B,z,L,A,R,22,s[15]),z,L,h,5,s[16]),L=f(L,A,B,z,v,9,s[17]),z=f(z,L,A,B,k,14,s[18]),B=f(B,z,L,A,a,20,s[19]),A=f(A,B,z,L,g,5,s[20]),L=f(L,A,B,z,m,9,s[21]),z=f(z,L,A,B,R,14,s[22]),B=f(B,z,L,A,_,20,s[23]),A=f(A,B,z,L,y,5,s[24]),L=f(L,A,B,z,x,9,s[25]),z=f(z,L,A,B,p,14,s[26]),B=f(B,z,L,A,b,20,s[27]),A=f(A,B,z,L,S,5,s[28]),L=f(L,A,B,z,d,9,s[29]),z=f(z,L,A,B,w,14,s[30]),A=c(A,B=f(B,z,L,A,E,20,s[31]),z,L,g,4,s[32]),L=c(L,A,B,z,b,11,s[33]),z=c(z,L,A,B,k,16,s[34]),B=c(B,z,L,A,x,23,s[35]),A=c(A,B,z,L,h,4,s[36]),L=c(L,A,B,z,_,11,s[37]),z=c(z,L,A,B,w,16,s[38]),B=c(B,z,L,A,m,23,s[39]),A=c(A,B,z,L,S,4,s[40]),L=c(L,A,B,z,a,11,s[41]),z=c(z,L,A,B,p,16,s[42]),B=c(B,z,L,A,v,23,s[43]),A=c(A,B,z,L,y,4,s[44]),L=c(L,A,B,z,E,11,s[45]),z=c(z,L,A,B,R,16,s[46]),A=u(A,B=c(B,z,L,A,d,23,s[47]),z,L,a,6,s[48]),L=u(L,A,B,z,w,10,s[49]),z=u(z,L,A,B,x,15,s[50]),B=u(B,z,L,A,g,21,s[51]),A=u(A,B,z,L,E,6,s[52]),L=u(L,A,B,z,p,10,s[53]),z=u(z,L,A,B,m,15,s[54]),B=u(B,z,L,A,h,21,s[55]),A=u(A,B,z,L,b,6,s[56]),L=u(L,A,B,z,R,10,s[57]),z=u(z,L,A,B,v,15,s[58]),B=u(B,z,L,A,S,21,s[59]),A=u(A,B,z,L,_,6,s[60]),L=u(L,A,B,z,k,10,s[61]),z=u(z,L,A,B,d,15,s[62]),B=u(B,z,L,A,y,21,s[63]),o[0]=o[0]+A|0,o[1]=o[1]+B|0,o[2]=o[2]+z|0,o[3]=o[3]+L|0},_doFinalize:function(){var t=this._data,r=t.words,n=8*this._nDataBytes,i=8*t.sigBytes;r[i>>>5]|=128<<24-i%32;var o=e.floor(n/4294967296),a=n;r[15+(i+64>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),r[14+(i+64>>>9<<4)]=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),t.sigBytes=4*(r.length+1),this._process();for(var s=this._hash,h=s.words,l=0;l<4;l++){var f=h[l];h[l]=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8)}return s},clone:function(){var e=o.clone.call(this);return e._hash=this._hash.clone(),e}});function l(e,t,r,n,i,o,a){var s=e+(t&r|~t&n)+i+a;return(s<<o|s>>>32-o)+t}function f(e,t,r,n,i,o,a){var s=e+(t&n|r&~n)+i+a;return(s<<o|s>>>32-o)+t}function c(e,t,r,n,i,o,a){var s=e+(t^r^n)+i+a;return(s<<o|s>>>32-o)+t}function u(e,t,r,n,i,o,a){var s=e+(r^(t|~n))+i+a;return(s<<o|s>>>32-o)+t}t.MD5=o._createHelper(h),t.HmacMD5=o._createHmacHelper(h)}(Math),r.MD5)}),Q(function(e,t){var r,n,i,o,a,s,h,l;e.exports=(i=(n=r=ee).lib,o=i.WordArray,a=i.Hasher,s=n.algo,h=[],l=s.SHA1=a.extend({_doReset:function(){this._hash=new o.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(e,t){for(var r=this._hash.words,n=r[0],i=r[1],o=r[2],a=r[3],s=r[4],l=0;l<80;l++){if(l<16)h[l]=0|e[t+l];else{var f=h[l-3]^h[l-8]^h[l-14]^h[l-16];h[l]=f<<1|f>>>31}var c=(n<<5|n>>>27)+s+h[l];c+=l<20?1518500249+(i&o|~i&a):l<40?1859775393+(i^o^a):l<60?(i&o|i&a|o&a)-1894007588:(i^o^a)-899497514,s=a,a=o,o=i<<30|i>>>2,i=n,n=c}r[0]=r[0]+n|0,r[1]=r[1]+i|0,r[2]=r[2]+o|0,r[3]=r[3]+a|0,r[4]=r[4]+s|0},_doFinalize:function(){var e=this._data,t=e.words,r=8*this._nDataBytes,n=8*e.sigBytes;return t[n>>>5]|=128<<24-n%32,t[14+(n+64>>>9<<4)]=Math.floor(r/4294967296),t[15+(n+64>>>9<<4)]=r,e.sigBytes=4*t.length,this._process(),this._hash},clone:function(){var e=a.clone.call(this);return e._hash=this._hash.clone(),e}}),n.SHA1=a._createHelper(l),n.HmacSHA1=a._createHmacHelper(l),r.SHA1)}),Q(function(e,t){var r;e.exports=(r=ee,function(e){var t=r,n=t.lib,i=n.WordArray,o=n.Hasher,a=t.algo,s=[],h=[];!function(){function t(t){for(var r=e.sqrt(t),n=2;n<=r;n++)if(!(t%n))return!1;return!0}function r(e){return 4294967296*(e-(0|e))|0}for(var n=2,i=0;i<64;)t(n)&&(i<8&&(s[i]=r(e.pow(n,.5))),h[i]=r(e.pow(n,1/3)),i++),n++}();var l=[],f=a.SHA256=o.extend({_doReset:function(){this._hash=new i.init(s.slice(0))},_doProcessBlock:function(e,t){for(var r=this._hash.words,n=r[0],i=r[1],o=r[2],a=r[3],s=r[4],f=r[5],c=r[6],u=r[7],d=0;d<64;d++){if(d<16)l[d]=0|e[t+d];else{var p=l[d-15],_=(p<<25|p>>>7)^(p<<14|p>>>18)^p>>>3,g=l[d-2],v=(g<<15|g>>>17)^(g<<13|g>>>19)^g>>>10;l[d]=_+l[d-7]+v+l[d-16]}var w=n&i^n&o^i&o,b=(n<<30|n>>>2)^(n<<19|n>>>13)^(n<<10|n>>>22),y=u+((s<<26|s>>>6)^(s<<21|s>>>11)^(s<<7|s>>>25))+(s&f^~s&c)+h[d]+l[d];u=c,c=f,f=s,s=a+y|0,a=o,o=i,i=n,n=y+(b+w)|0}r[0]=r[0]+n|0,r[1]=r[1]+i|0,r[2]=r[2]+o|0,r[3]=r[3]+a|0,r[4]=r[4]+s|0,r[5]=r[5]+f|0,r[6]=r[6]+c|0,r[7]=r[7]+u|0},_doFinalize:function(){var t=this._data,r=t.words,n=8*this._nDataBytes,i=8*t.sigBytes;return r[i>>>5]|=128<<24-i%32,r[14+(i+64>>>9<<4)]=e.floor(n/4294967296),r[15+(i+64>>>9<<4)]=n,t.sigBytes=4*r.length,this._process(),this._hash},clone:function(){var e=o.clone.call(this);return e._hash=this._hash.clone(),e}});t.SHA256=o._createHelper(f),t.HmacSHA256=o._createHmacHelper(f)}(Math),r.SHA256)}),Q(function(e,t){var r,n,i,o,a,s;e.exports=(i=(n=r=ee).lib.WordArray,o=n.algo,a=o.SHA256,s=o.SHA224=a.extend({_doReset:function(){this._hash=new i.init([3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428])},_doFinalize:function(){var e=a._doFinalize.call(this);return e.sigBytes-=4,e}}),n.SHA224=a._createHelper(s),n.HmacSHA224=a._createHmacHelper(s),r.SHA224)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.Hasher,n=e.x64,i=n.Word,o=n.WordArray,a=e.algo;function s(){return i.create.apply(i,arguments)}var h=[s(1116352408,3609767458),s(1899447441,602891725),s(3049323471,3964484399),s(3921009573,2173295548),s(961987163,4081628472),s(1508970993,3053834265),s(2453635748,2937671579),s(2870763221,3664609560),s(3624381080,2734883394),s(310598401,1164996542),s(607225278,1323610764),s(1426881987,3590304994),s(1925078388,4068182383),s(2162078206,991336113),s(2614888103,633803317),s(3248222580,3479774868),s(3835390401,2666613458),s(4022224774,944711139),s(264347078,2341262773),s(604807628,2007800933),s(770255983,1495990901),s(1249150122,1856431235),s(1555081692,3175218132),s(1996064986,2198950837),s(2554220882,3999719339),s(2821834349,766784016),s(2952996808,2566594879),s(3210313671,3203337956),s(3336571891,1034457026),s(3584528711,2466948901),s(113926993,3758326383),s(338241895,168717936),s(666307205,1188179964),s(773529912,1546045734),s(1294757372,1522805485),s(1396182291,2643833823),s(1695183700,2343527390),s(1986661051,1014477480),s(2177026350,1206759142),s(2456956037,344077627),s(2730485921,1290863460),s(2820302411,3158454273),s(3259730800,3505952657),s(3345764771,106217008),s(3516065817,3606008344),s(3600352804,1432725776),s(4094571909,1467031594),s(275423344,851169720),s(430227734,3100823752),s(506948616,1363258195),s(659060556,3750685593),s(883997877,3785050280),s(958139571,3318307427),s(1322822218,3812723403),s(1537002063,2003034995),s(1747873779,3602036899),s(1955562222,1575990012),s(2024104815,1125592928),s(2227730452,2716904306),s(2361852424,442776044),s(2428436474,593698344),s(2756734187,3733110249),s(3204031479,2999351573),s(3329325298,3815920427),s(3391569614,3928383900),s(3515267271,566280711),s(3940187606,3454069534),s(4118630271,4000239992),s(116418474,1914138554),s(174292421,2731055270),s(289380356,3203993006),s(460393269,320620315),s(685471733,587496836),s(852142971,1086792851),s(1017036298,365543100),s(1126000580,2618297676),s(1288033470,3409855158),s(1501505948,4234509866),s(1607167915,987167468),s(1816402316,1246189591)],l=[];!function(){for(var e=0;e<80;e++)l[e]=s()}();var f=a.SHA512=t.extend({_doReset:function(){this._hash=new o.init([new i.init(1779033703,4089235720),new i.init(3144134277,2227873595),new i.init(1013904242,4271175723),new i.init(2773480762,1595750129),new i.init(1359893119,2917565137),new i.init(2600822924,725511199),new i.init(528734635,4215389547),new i.init(1541459225,327033209)])},_doProcessBlock:function(e,t){for(var r=this._hash.words,n=r[0],i=r[1],o=r[2],a=r[3],s=r[4],f=r[5],c=r[6],u=r[7],d=n.high,p=n.low,_=i.high,g=i.low,v=o.high,w=o.low,b=a.high,y=a.low,m=s.high,k=s.low,E=f.high,S=f.low,x=c.high,R=c.low,A=u.high,B=u.low,z=d,L=p,T=_,M=g,C=v,D=w,I=b,P=y,O=m,U=k,H=E,F=S,N=x,Z=R,j=A,W=B,Y=0;Y<80;Y++){var K=l[Y];if(Y<16)var X=K.high=0|e[t+2*Y],q=K.low=0|e[t+2*Y+1];else{var V=l[Y-15],G=V.high,$=V.low,J=(G>>>1|$<<31)^(G>>>8|$<<24)^G>>>7,Q=($>>>1|G<<31)^($>>>8|G<<24)^($>>>7|G<<25),ee=l[Y-2],te=ee.high,re=ee.low,ne=(te>>>19|re<<13)^(te<<3|re>>>29)^te>>>6,ie=(re>>>19|te<<13)^(re<<3|te>>>29)^(re>>>6|te<<26),oe=l[Y-7],ae=oe.high,se=oe.low,he=l[Y-16],le=he.high,fe=he.low;X=(X=(X=J+ae+((q=Q+se)>>>0<Q>>>0?1:0))+ne+((q+=ie)>>>0<ie>>>0?1:0))+le+((q+=fe)>>>0<fe>>>0?1:0),K.high=X,K.low=q}var ce,ue=O&H^~O&N,de=U&F^~U&Z,pe=z&T^z&C^T&C,_e=L&M^L&D^M&D,ge=(z>>>28|L<<4)^(z<<30|L>>>2)^(z<<25|L>>>7),ve=(L>>>28|z<<4)^(L<<30|z>>>2)^(L<<25|z>>>7),we=(O>>>14|U<<18)^(O>>>18|U<<14)^(O<<23|U>>>9),be=(U>>>14|O<<18)^(U>>>18|O<<14)^(U<<23|O>>>9),ye=h[Y],me=ye.high,ke=ye.low,Ee=j+we+((ce=W+be)>>>0<W>>>0?1:0),Se=ve+_e;j=N,W=Z,N=H,Z=F,H=O,F=U,O=I+(Ee=(Ee=(Ee=Ee+ue+((ce+=de)>>>0<de>>>0?1:0))+me+((ce+=ke)>>>0<ke>>>0?1:0))+X+((ce+=q)>>>0<q>>>0?1:0))+((U=P+ce|0)>>>0<P>>>0?1:0)|0,I=C,P=D,C=T,D=M,T=z,M=L,z=Ee+(ge+pe+(Se>>>0<ve>>>0?1:0))+((L=ce+Se|0)>>>0<ce>>>0?1:0)|0}p=n.low=p+L,n.high=d+z+(p>>>0<L>>>0?1:0),g=i.low=g+M,i.high=_+T+(g>>>0<M>>>0?1:0),w=o.low=w+D,o.high=v+C+(w>>>0<D>>>0?1:0),y=a.low=y+P,a.high=b+I+(y>>>0<P>>>0?1:0),k=s.low=k+U,s.high=m+O+(k>>>0<U>>>0?1:0),S=f.low=S+F,f.high=E+H+(S>>>0<F>>>0?1:0),R=c.low=R+Z,c.high=x+N+(R>>>0<Z>>>0?1:0),B=u.low=B+W,u.high=A+j+(B>>>0<W>>>0?1:0)},_doFinalize:function(){var e=this._data,t=e.words,r=8*this._nDataBytes,n=8*e.sigBytes;return t[n>>>5]|=128<<24-n%32,t[30+(n+128>>>10<<5)]=Math.floor(r/4294967296),t[31+(n+128>>>10<<5)]=r,e.sigBytes=4*t.length,this._process(),this._hash.toX32()},clone:function(){var e=t.clone.call(this);return e._hash=this._hash.clone(),e},blockSize:32});e.SHA512=t._createHelper(f),e.HmacSHA512=t._createHmacHelper(f)}(),r.SHA512)}),Q(function(e,t){var r,n,i,o,a,s,h,l;e.exports=(i=(n=r=ee).x64,o=i.Word,a=i.WordArray,s=n.algo,h=s.SHA512,l=s.SHA384=h.extend({_doReset:function(){this._hash=new a.init([new o.init(3418070365,3238371032),new o.init(1654270250,914150663),new o.init(2438529370,812702999),new o.init(355462360,4144912697),new o.init(1731405415,4290775857),new o.init(2394180231,1750603025),new o.init(3675008525,1694076839),new o.init(1203062813,3204075428)])},_doFinalize:function(){var e=h._doFinalize.call(this);return e.sigBytes-=16,e}}),n.SHA384=h._createHelper(l),n.HmacSHA384=h._createHmacHelper(l),r.SHA384)}),Q(function(e,t){var r;e.exports=(r=ee,function(e){var t=r,n=t.lib,i=n.WordArray,o=n.Hasher,a=t.x64.Word,s=t.algo,h=[],l=[],f=[];!function(){for(var e=1,t=0,r=0;r<24;r++){h[e+5*t]=(r+1)*(r+2)/2%64;var n=(2*e+3*t)%5;e=t%5,t=n}for(e=0;e<5;e++)for(t=0;t<5;t++)l[e+5*t]=t+(2*e+3*t)%5*5;for(var i=1,o=0;o<24;o++){for(var s=0,c=0,u=0;u<7;u++){if(1&i){var d=(1<<u)-1;d<32?c^=1<<d:s^=1<<d-32}128&i?i=i<<1^113:i<<=1}f[o]=a.create(s,c)}}();var c=[];!function(){for(var e=0;e<25;e++)c[e]=a.create()}();var u=s.SHA3=o.extend({cfg:o.cfg.extend({outputLength:512}),_doReset:function(){for(var e=this._state=[],t=0;t<25;t++)e[t]=new a.init;this.blockSize=(1600-2*this.cfg.outputLength)/32},_doProcessBlock:function(e,t){for(var r=this._state,n=this.blockSize/2,i=0;i<n;i++){var o=e[t+2*i],a=e[t+2*i+1];o=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),a=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),(B=r[i]).high^=a,B.low^=o}for(var s=0;s<24;s++){for(var u=0;u<5;u++){for(var d=0,p=0,_=0;_<5;_++)d^=(B=r[u+5*_]).high,p^=B.low;var g=c[u];g.high=d,g.low=p}for(u=0;u<5;u++){var v=c[(u+4)%5],w=c[(u+1)%5],b=w.high,y=w.low;for(d=v.high^(b<<1|y>>>31),p=v.low^(y<<1|b>>>31),_=0;_<5;_++)(B=r[u+5*_]).high^=d,B.low^=p}for(var m=1;m<25;m++){var k=(B=r[m]).high,E=B.low,S=h[m];S<32?(d=k<<S|E>>>32-S,p=E<<S|k>>>32-S):(d=E<<S-32|k>>>64-S,p=k<<S-32|E>>>64-S);var x=c[l[m]];x.high=d,x.low=p}var R=c[0],A=r[0];for(R.high=A.high,R.low=A.low,u=0;u<5;u++)for(_=0;_<5;_++){var B=r[m=u+5*_],z=c[m],L=c[(u+1)%5+5*_],T=c[(u+2)%5+5*_];B.high=z.high^~L.high&T.high,B.low=z.low^~L.low&T.low}B=r[0];var M=f[s];B.high^=M.high,B.low^=M.low}},_doFinalize:function(){var t=this._data,r=t.words,n=(this._nDataBytes,8*t.sigBytes),o=32*this.blockSize;r[n>>>5]|=1<<24-n%32,r[(e.ceil((n+1)/o)*o>>>5)-1]|=128,t.sigBytes=4*r.length,this._process();for(var a=this._state,s=this.cfg.outputLength/8,h=s/8,l=[],f=0;f<h;f++){var c=a[f],u=c.high,d=c.low;u=16711935&(u<<8|u>>>24)|4278255360&(u<<24|u>>>8),d=16711935&(d<<8|d>>>24)|4278255360&(d<<24|d>>>8),l.push(d),l.push(u)}return new i.init(l,s)},clone:function(){for(var e=o.clone.call(this),t=e._state=this._state.slice(0),r=0;r<25;r++)t[r]=t[r].clone();return e}});t.SHA3=o._createHelper(u),t.HmacSHA3=o._createHmacHelper(u)}(Math),r.SHA3)}),Q(function(e,t){var r;e.exports=(r=ee,function(e){var t=r,n=t.lib,i=n.WordArray,o=n.Hasher,a=t.algo,s=i.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),h=i.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),l=i.create([11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),f=i.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),c=i.create([0,1518500249,1859775393,2400959708,2840853838]),u=i.create([1352829926,1548603684,1836072691,2053994217,0]),d=a.RIPEMD160=o.extend({_doReset:function(){this._hash=i.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(e,t){for(var r=0;r<16;r++){var n=t+r,i=e[n];e[n]=16711935&(i<<8|i>>>24)|4278255360&(i<<24|i>>>8)}var o,a,d,y,m,k,E,S,x,R,A,B=this._hash.words,z=c.words,L=u.words,T=s.words,M=h.words,C=l.words,D=f.words;for(k=o=B[0],E=a=B[1],S=d=B[2],x=y=B[3],R=m=B[4],r=0;r<80;r+=1)A=o+e[t+T[r]]|0,A+=r<16?p(a,d,y)+z[0]:r<32?_(a,d,y)+z[1]:r<48?g(a,d,y)+z[2]:r<64?v(a,d,y)+z[3]:w(a,d,y)+z[4],A=(A=b(A|=0,C[r]))+m|0,o=m,m=y,y=b(d,10),d=a,a=A,A=k+e[t+M[r]]|0,A+=r<16?w(E,S,x)+L[0]:r<32?v(E,S,x)+L[1]:r<48?g(E,S,x)+L[2]:r<64?_(E,S,x)+L[3]:p(E,S,x)+L[4],A=(A=b(A|=0,D[r]))+R|0,k=R,R=x,x=b(S,10),S=E,E=A;A=B[1]+d+x|0,B[1]=B[2]+y+R|0,B[2]=B[3]+m+k|0,B[3]=B[4]+o+E|0,B[4]=B[0]+a+S|0,B[0]=A},_doFinalize:function(){var e=this._data,t=e.words,r=8*this._nDataBytes,n=8*e.sigBytes;t[n>>>5]|=128<<24-n%32,t[14+(n+64>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),e.sigBytes=4*(t.length+1),this._process();for(var i=this._hash,o=i.words,a=0;a<5;a++){var s=o[a];o[a]=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8)}return i},clone:function(){var e=o.clone.call(this);return e._hash=this._hash.clone(),e}});function p(e,t,r){return e^t^r}function _(e,t,r){return e&t|~e&r}function g(e,t,r){return(e|~t)^r}function v(e,t,r){return e&r|t&~r}function w(e,t,r){return e^(t|~r)}function b(e,t){return e<<t|e>>>32-t}t.RIPEMD160=o._createHelper(d),t.HmacRIPEMD160=o._createHmacHelper(d)}(),r.RIPEMD160)}),Q(function(e,t){var r,n,i,o,a,s;e.exports=(n=(r=ee).lib,i=n.Base,o=r.enc,a=o.Utf8,s=r.algo,void(s.HMAC=i.extend({init:function(e,t){e=this._hasher=new e.init,"string"==typeof t&&(t=a.parse(t));var r=e.blockSize,n=4*r;t.sigBytes>n&&(t=e.finalize(t)),t.clamp();for(var i=this._oKey=t.clone(),o=this._iKey=t.clone(),s=i.words,h=o.words,l=0;l<r;l++)s[l]^=1549556828,h[l]^=909522486;i.sigBytes=o.sigBytes=n,this.reset()},reset:function(){var e=this._hasher;e.reset(),e.update(this._iKey)},update:function(e){return this._hasher.update(e),this},finalize:function(e){var t=this._hasher,r=t.finalize(e);t.reset();var n=t.finalize(this._oKey.clone().concat(r));return n}})))}),Q(function(e,t){var r,n,i,o,a,s,h,l,f;e.exports=(i=(n=r=ee).lib,o=i.Base,a=i.WordArray,s=n.algo,h=s.SHA1,l=s.HMAC,f=s.PBKDF2=o.extend({cfg:o.extend({keySize:4,hasher:h,iterations:1}),init:function(e){this.cfg=this.cfg.extend(e)},compute:function(e,t){for(var r=this.cfg,n=l.create(r.hasher,e),i=a.create(),o=a.create([1]),s=i.words,h=o.words,f=r.keySize,c=r.iterations;s.length<f;){var u=n.update(t).finalize(o);n.reset();for(var d=u.words,p=d.length,_=u,g=1;g<c;g++){_=n.finalize(_),n.reset();for(var v=_.words,w=0;w<p;w++)d[w]^=v[w]}i.concat(u),h[0]++}return i.sigBytes=4*f,i}}),n.PBKDF2=function(e,t,r){return f.create(r).compute(e,t)},r.PBKDF2)}),Q(function(e,t){var r,n,i,o,a,s,h,l;e.exports=(i=(n=r=ee).lib,o=i.Base,a=i.WordArray,s=n.algo,h=s.MD5,l=s.EvpKDF=o.extend({cfg:o.extend({keySize:4,hasher:h,iterations:1}),init:function(e){this.cfg=this.cfg.extend(e)},compute:function(e,t){for(var r=this.cfg,n=r.hasher.create(),i=a.create(),o=i.words,s=r.keySize,h=r.iterations;o.length<s;){l&&n.update(l);var l=n.update(e).finalize(t);n.reset();for(var f=1;f<h;f++)l=n.finalize(l),n.reset();i.concat(l)}return i.sigBytes=4*s,i}}),n.EvpKDF=function(e,t,r){return l.create(r).compute(e,t)},r.EvpKDF)}),Q(function(e,t){var r,n,i,o,a,s,h,l,f,c,u,d,p,_,g,v,w,b,y,m,k,E,S,x;e.exports=void((r=ee).lib.Cipher||(i=r,o=i.lib,a=o.Base,s=o.WordArray,h=o.BufferedBlockAlgorithm,l=i.enc,l.Utf8,f=l.Base64,c=i.algo,u=c.EvpKDF,d=o.Cipher=h.extend({cfg:a.extend(),createEncryptor:function(e,t){return this.create(this._ENC_XFORM_MODE,e,t)},createDecryptor:function(e,t){return this.create(this._DEC_XFORM_MODE,e,t)},init:function(e,t,r){this.cfg=this.cfg.extend(r),this._xformMode=e,this._key=t,this.reset()},reset:function(){h.reset.call(this),this._doReset()},process:function(e){return this._append(e),this._process()},finalize:function(e){e&&this._append(e);var t=this._doFinalize();return t},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){function e(e){return"string"==typeof e?x:k}return function(t){return{encrypt:function(r,n,i){return e(n).encrypt(t,r,n,i)},decrypt:function(r,n,i){return e(n).decrypt(t,r,n,i)}}}}()}),o.StreamCipher=d.extend({_doFinalize:function(){var e=this._process(!0);return e},blockSize:1}),p=i.mode={},_=o.BlockCipherMode=a.extend({createEncryptor:function(e,t){return this.Encryptor.create(e,t)},createDecryptor:function(e,t){return this.Decryptor.create(e,t)},init:function(e,t){this._cipher=e,this._iv=t}}),g=p.CBC=function(){var e=_.extend();function t(e,t,r){var i=this._iv;if(i){var o=i;this._iv=n}else var o=this._prevBlock;for(var a=0;a<r;a++)e[t+a]^=o[a]}return e.Encryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize;t.call(this,e,r,i),n.encryptBlock(e,r),this._prevBlock=e.slice(r,r+i)}}),e.Decryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize,o=e.slice(r,r+i);n.decryptBlock(e,r),t.call(this,e,r,i),this._prevBlock=o}}),e}(),v=i.pad={},w=v.Pkcs7={pad:function(e,t){for(var r=4*t,n=r-e.sigBytes%r,i=n<<24|n<<16|n<<8|n,o=[],a=0;a<n;a+=4)o.push(i);var h=s.create(o,n);e.concat(h)},unpad:function(e){var t=255&e.words[e.sigBytes-1>>>2];e.sigBytes-=t}},o.BlockCipher=d.extend({cfg:d.cfg.extend({mode:g,padding:w}),reset:function(){d.reset.call(this);var e=this.cfg,t=e.iv,r=e.mode;if(this._xformMode==this._ENC_XFORM_MODE)var n=r.createEncryptor;else{var n=r.createDecryptor;this._minBufferSize=1}this._mode&&this._mode.__creator==n?this._mode.init(this,t&&t.words):(this._mode=n.call(r,this,t&&t.words),this._mode.__creator=n)},_doProcessBlock:function(e,t){this._mode.processBlock(e,t)},_doFinalize:function(){var e=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){e.pad(this._data,this.blockSize);var t=this._process(!0)}else{var t=this._process(!0);e.unpad(t)}return t},blockSize:4}),b=o.CipherParams=a.extend({init:function(e){this.mixIn(e)},toString:function(e){return(e||this.formatter).stringify(this)}}),y=i.format={},m=y.OpenSSL={stringify:function(e){var t=e.ciphertext,r=e.salt;if(r)var n=s.create([1398893684,1701076831]).concat(r).concat(t);else var n=t;return n.toString(f)},parse:function(e){var t=f.parse(e),r=t.words;if(1398893684==r[0]&&1701076831==r[1]){var n=s.create(r.slice(2,4));r.splice(0,4),t.sigBytes-=16}return b.create({ciphertext:t,salt:n})}},k=o.SerializableCipher=a.extend({cfg:a.extend({format:m}),encrypt:function(e,t,r,n){n=this.cfg.extend(n);var i=e.createEncryptor(r,n),o=i.finalize(t),a=i.cfg;return b.create({ciphertext:o,key:r,iv:a.iv,algorithm:e,mode:a.mode,padding:a.padding,blockSize:e.blockSize,formatter:n.format})},decrypt:function(e,t,r,n){n=this.cfg.extend(n),t=this._parse(t,n.format);var i=e.createDecryptor(r,n).finalize(t.ciphertext);return i},_parse:function(e,t){return"string"==typeof e?t.parse(e,this):e}}),E=i.kdf={},S=E.OpenSSL={execute:function(e,t,r,n){n||(n=s.random(8));var i=u.create({keySize:t+r}).compute(e,n),o=s.create(i.words.slice(t),4*r);return i.sigBytes=4*t,b.create({key:i,iv:o,salt:n})}},x=o.PasswordBasedCipher=k.extend({cfg:k.cfg.extend({kdf:S}),encrypt:function(e,t,r,n){var i=(n=this.cfg.extend(n)).kdf.execute(r,e.keySize,e.ivSize);n.iv=i.iv;var o=k.encrypt.call(this,e,t,i.key,n);return o.mixIn(i),o},decrypt:function(e,t,r,n){n=this.cfg.extend(n),t=this._parse(t,n.format);var i=n.kdf.execute(r,e.keySize,e.ivSize,t.salt);n.iv=i.iv;var o=k.decrypt.call(this,e,t,i.key,n);return o}})))}),Q(function(e,t){var r;e.exports=((r=ee).mode.CFB=function(){var e=r.lib.BlockCipherMode.extend();function t(e,t,r,n){var i=this._iv;if(i){var o=i.slice(0);this._iv=void 0}else o=this._prevBlock;n.encryptBlock(o,0);for(var a=0;a<r;a++)e[t+a]^=o[a]}return e.Encryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize;t.call(this,e,r,i,n),this._prevBlock=e.slice(r,r+i)}}),e.Decryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize,o=e.slice(r,r+i);t.call(this,e,r,i,n),this._prevBlock=o}}),e}(),r.mode.CFB)}),Q(function(e,t){var r,n,i;e.exports=((r=ee).mode.CTR=(n=r.lib.BlockCipherMode.extend(),i=n.Encryptor=n.extend({processBlock:function(e,t){var r=this._cipher,n=r.blockSize,i=this._iv,o=this._counter;i&&(o=this._counter=i.slice(0),this._iv=void 0);var a=o.slice(0);r.encryptBlock(a,0),o[n-1]=o[n-1]+1|0;for(var s=0;s<n;s++)e[t+s]^=a[s]}}),n.Decryptor=i,n),r.mode.CTR)}),Q(function(e,t){var r;e.exports=((r=ee).mode.CTRGladman=function(){var e=r.lib.BlockCipherMode.extend();function t(e){if(255==(e>>24&255)){var t=e>>16&255,r=e>>8&255,n=255&e;255===t?(t=0,255===r?(r=0,255===n?n=0:++n):++r):++t,e=0,e+=t<<16,e+=r<<8,e+=n}else e+=1<<24;return e}var n=e.Encryptor=e.extend({processBlock:function(e,r){var n=this._cipher,i=n.blockSize,o=this._iv,a=this._counter;o&&(a=this._counter=o.slice(0),this._iv=void 0),function(e){0===(e[0]=t(e[0]))&&(e[1]=t(e[1]))}(a);var s=a.slice(0);n.encryptBlock(s,0);for(var h=0;h<i;h++)e[r+h]^=s[h]}});return e.Decryptor=n,e}(),r.mode.CTRGladman)}),Q(function(e,t){var r,n,i;e.exports=((r=ee).mode.OFB=(n=r.lib.BlockCipherMode.extend(),i=n.Encryptor=n.extend({processBlock:function(e,t){var r=this._cipher,n=r.blockSize,i=this._iv,o=this._keystream;i&&(o=this._keystream=i.slice(0),this._iv=void 0),r.encryptBlock(o,0);for(var a=0;a<n;a++)e[t+a]^=o[a]}}),n.Decryptor=i,n),r.mode.OFB)}),Q(function(e,t){var r,n;e.exports=((r=ee).mode.ECB=((n=r.lib.BlockCipherMode.extend()).Encryptor=n.extend({processBlock:function(e,t){this._cipher.encryptBlock(e,t)}}),n.Decryptor=n.extend({processBlock:function(e,t){this._cipher.decryptBlock(e,t)}}),n),r.mode.ECB)}),Q(function(e,t){var r;e.exports=((r=ee).pad.AnsiX923={pad:function(e,t){var r=e.sigBytes,n=4*t,i=n-r%n,o=r+i-1;e.clamp(),e.words[o>>>2]|=i<<24-o%4*8,e.sigBytes+=i},unpad:function(e){var t=255&e.words[e.sigBytes-1>>>2];e.sigBytes-=t}},r.pad.Ansix923)}),Q(function(e,t){var r;e.exports=((r=ee).pad.Iso10126={pad:function(e,t){var n=4*t,i=n-e.sigBytes%n;e.concat(r.lib.WordArray.random(i-1)).concat(r.lib.WordArray.create([i<<24],1))},unpad:function(e){var t=255&e.words[e.sigBytes-1>>>2];e.sigBytes-=t}},r.pad.Iso10126)}),Q(function(e,t){var r;e.exports=((r=ee).pad.Iso97971={pad:function(e,t){e.concat(r.lib.WordArray.create([2147483648],1)),r.pad.ZeroPadding.pad(e,t)},unpad:function(e){r.pad.ZeroPadding.unpad(e),e.sigBytes--}},r.pad.Iso97971)}),Q(function(e,t){var r;e.exports=((r=ee).pad.ZeroPadding={pad:function(e,t){var r=4*t;e.clamp(),e.sigBytes+=r-(e.sigBytes%r||r)},unpad:function(e){for(var t=e.words,r=e.sigBytes-1;!(t[r>>>2]>>>24-r%4*8&255);)r--;e.sigBytes=r+1}},r.pad.ZeroPadding)}),Q(function(e,t){var r;e.exports=((r=ee).pad.NoPadding={pad:function(){},unpad:function(){}},r.pad.NoPadding)}),Q(function(e,t){var r,n,i,o;e.exports=(i=(n=r=ee).lib.CipherParams,o=n.enc.Hex,n.format.Hex={stringify:function(e){return e.ciphertext.toString(o)},parse:function(e){var t=o.parse(e);return i.create({ciphertext:t})}},r.format.Hex)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.BlockCipher,n=e.algo,i=[],o=[],a=[],s=[],h=[],l=[],f=[],c=[],u=[],d=[];!function(){for(var e=[],t=0;t<256;t++)e[t]=t<128?t<<1:t<<1^283;var r=0,n=0;for(t=0;t<256;t++){var p=n^n<<1^n<<2^n<<3^n<<4;p=p>>>8^255&p^99,i[r]=p,o[p]=r;var _=e[r],g=e[_],v=e[g],w=257*e[p]^16843008*p;a[r]=w<<24|w>>>8,s[r]=w<<16|w>>>16,h[r]=w<<8|w>>>24,l[r]=w,w=16843009*v^65537*g^257*_^16843008*r,f[p]=w<<24|w>>>8,c[p]=w<<16|w>>>16,u[p]=w<<8|w>>>24,d[p]=w,r?(r=_^e[e[e[v^_]]],n^=e[e[n]]):r=n=1}}();var p=[0,1,2,4,8,16,32,64,128,27,54],_=n.AES=t.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var e=this._keyPriorReset=this._key,t=e.words,r=e.sigBytes/4,n=4*((this._nRounds=r+6)+1),o=this._keySchedule=[],a=0;a<n;a++)if(a<r)o[a]=t[a];else{var s=o[a-1];a%r?r>6&&a%r==4&&(s=i[s>>>24]<<24|i[s>>>16&255]<<16|i[s>>>8&255]<<8|i[255&s]):(s=i[(s=s<<8|s>>>24)>>>24]<<24|i[s>>>16&255]<<16|i[s>>>8&255]<<8|i[255&s],s^=p[a/r|0]<<24),o[a]=o[a-r]^s}for(var h=this._invKeySchedule=[],l=0;l<n;l++)a=n-l,s=l%4?o[a]:o[a-4],h[l]=l<4||a<=4?s:f[i[s>>>24]]^c[i[s>>>16&255]]^u[i[s>>>8&255]]^d[i[255&s]]}},encryptBlock:function(e,t){this._doCryptBlock(e,t,this._keySchedule,a,s,h,l,i)},decryptBlock:function(e,t){var r=e[t+1];e[t+1]=e[t+3],e[t+3]=r,this._doCryptBlock(e,t,this._invKeySchedule,f,c,u,d,o),r=e[t+1],e[t+1]=e[t+3],e[t+3]=r},_doCryptBlock:function(e,t,r,n,i,o,a,s){for(var h=this._nRounds,l=e[t]^r[0],f=e[t+1]^r[1],c=e[t+2]^r[2],u=e[t+3]^r[3],d=4,p=1;p<h;p++){var _=n[l>>>24]^i[f>>>16&255]^o[c>>>8&255]^a[255&u]^r[d++],g=n[f>>>24]^i[c>>>16&255]^o[u>>>8&255]^a[255&l]^r[d++],v=n[c>>>24]^i[u>>>16&255]^o[l>>>8&255]^a[255&f]^r[d++],w=n[u>>>24]^i[l>>>16&255]^o[f>>>8&255]^a[255&c]^r[d++];l=_,f=g,c=v,u=w}_=(s[l>>>24]<<24|s[f>>>16&255]<<16|s[c>>>8&255]<<8|s[255&u])^r[d++],g=(s[f>>>24]<<24|s[c>>>16&255]<<16|s[u>>>8&255]<<8|s[255&l])^r[d++],v=(s[c>>>24]<<24|s[u>>>16&255]<<16|s[l>>>8&255]<<8|s[255&f])^r[d++],w=(s[u>>>24]<<24|s[l>>>16&255]<<16|s[f>>>8&255]<<8|s[255&c])^r[d++],e[t]=_,e[t+1]=g,e[t+2]=v,e[t+3]=w},keySize:8});e.AES=t._createHelper(_)}(),r.AES)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib,n=t.WordArray,i=t.BlockCipher,o=e.algo,a=[57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36,63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4],s=[14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32],h=[1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28],l=[{0:8421888,268435456:32768,536870912:8421378,805306368:2,1073741824:512,1342177280:8421890,1610612736:8389122,1879048192:8388608,2147483648:514,2415919104:8389120,2684354560:33280,2952790016:8421376,3221225472:32770,3489660928:8388610,3758096384:0,4026531840:33282,134217728:0,402653184:8421890,671088640:33282,939524096:32768,1207959552:8421888,1476395008:512,1744830464:8421378,2013265920:2,2281701376:8389120,2550136832:33280,2818572288:8421376,3087007744:8389122,3355443200:8388610,3623878656:32770,3892314112:514,4160749568:8388608,1:32768,268435457:2,536870913:8421888,805306369:8388608,1073741825:8421378,1342177281:33280,1610612737:512,1879048193:8389122,2147483649:8421890,2415919105:8421376,2684354561:8388610,2952790017:33282,3221225473:514,3489660929:8389120,3758096385:32770,4026531841:0,134217729:8421890,402653185:8421376,671088641:8388608,939524097:512,1207959553:32768,1476395009:8388610,1744830465:2,2013265921:33282,2281701377:32770,2550136833:8389122,2818572289:514,3087007745:8421888,3355443201:8389120,3623878657:0,3892314113:33280,4160749569:8421378},{0:1074282512,16777216:16384,33554432:524288,50331648:1074266128,67108864:1073741840,83886080:1074282496,100663296:1073758208,117440512:16,134217728:540672,150994944:1073758224,167772160:1073741824,184549376:540688,201326592:524304,218103808:0,234881024:16400,251658240:1074266112,8388608:1073758208,25165824:540688,41943040:16,58720256:1073758224,75497472:1074282512,92274688:1073741824,109051904:524288,125829120:1074266128,142606336:524304,159383552:0,176160768:16384,192937984:1074266112,209715200:1073741840,226492416:540672,243269632:1074282496,260046848:16400,268435456:0,285212672:1074266128,301989888:1073758224,318767104:1074282496,335544320:1074266112,352321536:16,369098752:540688,385875968:16384,402653184:16400,419430400:524288,436207616:524304,452984832:1073741840,469762048:540672,486539264:1073758208,503316480:1073741824,520093696:1074282512,276824064:540688,293601280:524288,310378496:1074266112,327155712:16384,343932928:1073758208,360710144:1074282512,377487360:16,394264576:1073741824,411041792:1074282496,427819008:1073741840,444596224:1073758224,461373440:524304,478150656:0,494927872:16400,511705088:1074266128,528482304:540672},{0:260,1048576:0,2097152:67109120,3145728:65796,4194304:65540,5242880:67108868,6291456:67174660,7340032:67174400,8388608:67108864,9437184:67174656,10485760:65792,11534336:67174404,12582912:67109124,13631488:65536,14680064:4,15728640:256,524288:67174656,1572864:67174404,2621440:0,3670016:67109120,4718592:67108868,5767168:65536,6815744:65540,7864320:260,8912896:4,9961472:256,11010048:67174400,12058624:65796,13107200:65792,14155776:67109124,15204352:67174660,16252928:67108864,16777216:67174656,17825792:65540,18874368:65536,19922944:67109120,20971520:256,22020096:67174660,23068672:67108868,24117248:0,25165824:67109124,26214400:67108864,27262976:4,28311552:65792,29360128:67174400,30408704:260,31457280:65796,32505856:67174404,17301504:67108864,18350080:260,19398656:67174656,20447232:0,21495808:65540,22544384:67109120,23592960:256,24641536:67174404,25690112:65536,26738688:67174660,27787264:65796,28835840:67108868,29884416:67109124,30932992:67174400,31981568:4,33030144:65792},{0:2151682048,65536:2147487808,131072:4198464,196608:2151677952,262144:0,327680:4198400,393216:2147483712,458752:4194368,524288:2147483648,589824:4194304,655360:64,720896:2147487744,786432:2151678016,851968:4160,917504:4096,983040:2151682112,32768:2147487808,98304:64,163840:2151678016,229376:2147487744,294912:4198400,360448:2151682112,425984:0,491520:2151677952,557056:4096,622592:2151682048,688128:4194304,753664:4160,819200:2147483648,884736:4194368,950272:4198464,1015808:2147483712,1048576:4194368,1114112:4198400,1179648:2147483712,1245184:0,1310720:4160,1376256:2151678016,1441792:2151682048,1507328:2147487808,1572864:2151682112,1638400:2147483648,1703936:2151677952,1769472:4198464,1835008:2147487744,1900544:4194304,1966080:64,2031616:4096,1081344:2151677952,1146880:2151682112,1212416:0,1277952:4198400,1343488:4194368,1409024:2147483648,1474560:2147487808,1540096:64,1605632:2147483712,1671168:4096,1736704:2147487744,1802240:2151678016,1867776:4160,1933312:2151682048,1998848:4194304,2064384:4198464},{0:128,4096:17039360,8192:262144,12288:536870912,16384:537133184,20480:16777344,24576:553648256,28672:262272,32768:16777216,36864:537133056,40960:536871040,45056:553910400,49152:553910272,53248:0,57344:17039488,61440:553648128,2048:17039488,6144:553648256,10240:128,14336:17039360,18432:262144,22528:537133184,26624:553910272,30720:536870912,34816:537133056,38912:0,43008:553910400,47104:16777344,51200:536871040,55296:553648128,59392:16777216,63488:262272,65536:262144,69632:128,73728:536870912,77824:553648256,81920:16777344,86016:553910272,90112:537133184,94208:16777216,98304:553910400,102400:553648128,106496:17039360,110592:537133056,114688:262272,118784:536871040,122880:0,126976:17039488,67584:553648256,71680:16777216,75776:17039360,79872:537133184,83968:536870912,88064:17039488,92160:128,96256:553910272,100352:262272,104448:553910400,108544:0,112640:553648128,116736:16777344,120832:262144,124928:537133056,129024:536871040},{0:268435464,256:8192,512:270532608,768:270540808,1024:268443648,1280:2097152,1536:2097160,1792:268435456,2048:0,2304:268443656,2560:2105344,2816:8,3072:270532616,3328:2105352,3584:8200,3840:270540800,128:270532608,384:270540808,640:8,896:2097152,1152:2105352,1408:268435464,1664:268443648,1920:8200,2176:2097160,2432:8192,2688:268443656,2944:270532616,3200:0,3456:270540800,3712:2105344,3968:268435456,4096:268443648,4352:270532616,4608:270540808,4864:8200,5120:2097152,5376:268435456,5632:268435464,5888:2105344,6144:2105352,6400:0,6656:8,6912:270532608,7168:8192,7424:268443656,7680:270540800,7936:2097160,4224:8,4480:2105344,4736:2097152,4992:268435464,5248:268443648,5504:8200,5760:270540808,6016:270532608,6272:270540800,6528:270532616,6784:8192,7040:2105352,7296:2097160,7552:0,7808:268435456,8064:268443656},{0:1048576,16:33555457,32:1024,48:1049601,64:34604033,80:0,96:1,112:34603009,128:33555456,144:1048577,160:33554433,176:34604032,192:34603008,208:1025,224:1049600,240:33554432,8:34603009,24:0,40:33555457,56:34604032,72:1048576,88:33554433,104:33554432,120:1025,136:1049601,152:33555456,168:34603008,184:1048577,200:1024,216:34604033,232:1,248:1049600,256:33554432,272:1048576,288:33555457,304:34603009,320:1048577,336:33555456,352:34604032,368:1049601,384:1025,400:34604033,416:1049600,432:1,448:0,464:34603008,480:33554433,496:1024,264:1049600,280:33555457,296:34603009,312:1,328:33554432,344:1048576,360:1025,376:34604032,392:33554433,408:34603008,424:0,440:34604033,456:1049601,472:1024,488:33555456,504:1048577},{0:134219808,1:131072,2:134217728,3:32,4:131104,5:134350880,6:134350848,7:2048,8:134348800,9:134219776,10:133120,11:134348832,12:2080,13:0,14:134217760,15:133152,2147483648:2048,2147483649:134350880,2147483650:134219808,2147483651:134217728,2147483652:134348800,2147483653:133120,2147483654:133152,2147483655:32,2147483656:134217760,2147483657:2080,2147483658:131104,2147483659:134350848,2147483660:0,2147483661:134348832,2147483662:134219776,2147483663:131072,16:133152,17:134350848,18:32,19:2048,20:134219776,21:134217760,22:134348832,23:131072,24:0,25:131104,26:134348800,27:134219808,28:134350880,29:133120,30:2080,31:134217728,2147483664:131072,2147483665:2048,2147483666:134348832,2147483667:133152,2147483668:32,2147483669:134348800,2147483670:134217728,2147483671:134219808,2147483672:134350880,2147483673:134217760,2147483674:134219776,2147483675:0,2147483676:133120,2147483677:2080,2147483678:131104,2147483679:134350848}],f=[4160749569,528482304,33030144,2064384,129024,8064,504,2147483679],c=o.DES=i.extend({_doReset:function(){for(var e=this._key.words,t=[],r=0;r<56;r++){var n=a[r]-1;t[r]=e[n>>>5]>>>31-n%32&1}for(var i=this._subKeys=[],o=0;o<16;o++){var l=i[o]=[],f=h[o];for(r=0;r<24;r++)l[r/6|0]|=t[(s[r]-1+f)%28]<<31-r%6,l[4+(r/6|0)]|=t[28+(s[r+24]-1+f)%28]<<31-r%6;for(l[0]=l[0]<<1|l[0]>>>31,r=1;r<7;r++)l[r]=l[r]>>>4*(r-1)+3;l[7]=l[7]<<5|l[7]>>>27}var c=this._invSubKeys=[];for(r=0;r<16;r++)c[r]=i[15-r]},encryptBlock:function(e,t){this._doCryptBlock(e,t,this._subKeys)},decryptBlock:function(e,t){this._doCryptBlock(e,t,this._invSubKeys)},_doCryptBlock:function(e,t,r){this._lBlock=e[t],this._rBlock=e[t+1],u.call(this,4,252645135),u.call(this,16,65535),d.call(this,2,858993459),d.call(this,8,16711935),u.call(this,1,1431655765);for(var n=0;n<16;n++){for(var i=r[n],o=this._lBlock,a=this._rBlock,s=0,h=0;h<8;h++)s|=l[h][((a^i[h])&f[h])>>>0];this._lBlock=a,this._rBlock=o^s}var c=this._lBlock;this._lBlock=this._rBlock,this._rBlock=c,u.call(this,1,1431655765),d.call(this,8,16711935),d.call(this,2,858993459),u.call(this,16,65535),u.call(this,4,252645135),e[t]=this._lBlock,e[t+1]=this._rBlock},keySize:2,ivSize:2,blockSize:2});function u(e,t){var r=(this._lBlock>>>e^this._rBlock)&t;this._rBlock^=r,this._lBlock^=r<<e}function d(e,t){var r=(this._rBlock>>>e^this._lBlock)&t;this._lBlock^=r,this._rBlock^=r<<e}e.DES=i._createHelper(c);var p=o.TripleDES=i.extend({_doReset:function(){var e=this._key.words;this._des1=c.createEncryptor(n.create(e.slice(0,2))),this._des2=c.createEncryptor(n.create(e.slice(2,4))),this._des3=c.createEncryptor(n.create(e.slice(4,6)))},encryptBlock:function(e,t){this._des1.encryptBlock(e,t),this._des2.decryptBlock(e,t),this._des3.encryptBlock(e,t)},decryptBlock:function(e,t){this._des3.decryptBlock(e,t),this._des2.encryptBlock(e,t),this._des1.decryptBlock(e,t)},keySize:6,ivSize:2,blockSize:2});e.TripleDES=i._createHelper(p)}(),r.TripleDES)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.StreamCipher,n=e.algo,i=n.RC4=t.extend({_doReset:function(){for(var e=this._key,t=e.words,r=e.sigBytes,n=this._S=[],i=0;i<256;i++)n[i]=i;i=0;for(var o=0;i<256;i++){var a=i%r,s=t[a>>>2]>>>24-a%4*8&255;o=(o+n[i]+s)%256;var h=n[i];n[i]=n[o],n[o]=h}this._i=this._j=0},_doProcessBlock:function(e,t){e[t]^=o.call(this)},keySize:8,ivSize:0});function o(){for(var e=this._S,t=this._i,r=this._j,n=0,i=0;i<4;i++){r=(r+e[t=(t+1)%256])%256;var o=e[t];e[t]=e[r],e[r]=o,n|=e[(e[t]+e[r])%256]<<24-8*i}return this._i=t,this._j=r,n}e.RC4=t._createHelper(i);var a=n.RC4Drop=i.extend({cfg:i.cfg.extend({drop:192}),_doReset:function(){i._doReset.call(this);for(var e=this.cfg.drop;e>0;e--)o.call(this)}});e.RC4Drop=t._createHelper(a)}(),r.RC4)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.StreamCipher,n=e.algo,i=[],o=[],a=[],s=n.Rabbit=t.extend({_doReset:function(){for(var e=this._key.words,t=this.cfg.iv,r=0;r<4;r++)e[r]=16711935&(e[r]<<8|e[r]>>>24)|4278255360&(e[r]<<24|e[r]>>>8);var n=this._X=[e[0],e[3]<<16|e[2]>>>16,e[1],e[0]<<16|e[3]>>>16,e[2],e[1]<<16|e[0]>>>16,e[3],e[2]<<16|e[1]>>>16],i=this._C=[e[2]<<16|e[2]>>>16,4294901760&e[0]|65535&e[1],e[3]<<16|e[3]>>>16,4294901760&e[1]|65535&e[2],e[0]<<16|e[0]>>>16,4294901760&e[2]|65535&e[3],e[1]<<16|e[1]>>>16,4294901760&e[3]|65535&e[0]];for(this._b=0,r=0;r<4;r++)h.call(this);for(r=0;r<8;r++)i[r]^=n[r+4&7];if(t){var o=t.words,a=o[0],s=o[1],l=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),f=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),c=l>>>16|4294901760&f,u=f<<16|65535&l;for(i[0]^=l,i[1]^=c,i[2]^=f,i[3]^=u,i[4]^=l,i[5]^=c,i[6]^=f,i[7]^=u,r=0;r<4;r++)h.call(this)}},_doProcessBlock:function(e,t){var r=this._X;h.call(this),i[0]=r[0]^r[5]>>>16^r[3]<<16,i[1]=r[2]^r[7]>>>16^r[5]<<16,i[2]=r[4]^r[1]>>>16^r[7]<<16,i[3]=r[6]^r[3]>>>16^r[1]<<16;for(var n=0;n<4;n++)i[n]=16711935&(i[n]<<8|i[n]>>>24)|4278255360&(i[n]<<24|i[n]>>>8),e[t+n]^=i[n]},blockSize:4,ivSize:2});function h(){for(var e=this._X,t=this._C,r=0;r<8;r++)o[r]=t[r];for(t[0]=t[0]+1295307597+this._b|0,t[1]=t[1]+3545052371+(t[0]>>>0<o[0]>>>0?1:0)|0,t[2]=t[2]+886263092+(t[1]>>>0<o[1]>>>0?1:0)|0,t[3]=t[3]+1295307597+(t[2]>>>0<o[2]>>>0?1:0)|0,t[4]=t[4]+3545052371+(t[3]>>>0<o[3]>>>0?1:0)|0,t[5]=t[5]+886263092+(t[4]>>>0<o[4]>>>0?1:0)|0,t[6]=t[6]+1295307597+(t[5]>>>0<o[5]>>>0?1:0)|0,t[7]=t[7]+3545052371+(t[6]>>>0<o[6]>>>0?1:0)|0,this._b=t[7]>>>0<o[7]>>>0?1:0,r=0;r<8;r++){var n=e[r]+t[r],i=65535&n,s=n>>>16,h=((i*i>>>17)+i*s>>>15)+s*s,l=((4294901760&n)*n|0)+((65535&n)*n|0);a[r]=h^l}e[0]=a[0]+(a[7]<<16|a[7]>>>16)+(a[6]<<16|a[6]>>>16)|0,e[1]=a[1]+(a[0]<<8|a[0]>>>24)+a[7]|0,e[2]=a[2]+(a[1]<<16|a[1]>>>16)+(a[0]<<16|a[0]>>>16)|0,e[3]=a[3]+(a[2]<<8|a[2]>>>24)+a[1]|0,e[4]=a[4]+(a[3]<<16|a[3]>>>16)+(a[2]<<16|a[2]>>>16)|0,e[5]=a[5]+(a[4]<<8|a[4]>>>24)+a[3]|0,e[6]=a[6]+(a[5]<<16|a[5]>>>16)+(a[4]<<16|a[4]>>>16)|0,e[7]=a[7]+(a[6]<<8|a[6]>>>24)+a[5]|0}e.Rabbit=t._createHelper(s)}(),r.Rabbit)}),Q(function(e,t){var r;e.exports=(r=ee,function(){var e=r,t=e.lib.StreamCipher,n=e.algo,i=[],o=[],a=[],s=n.RabbitLegacy=t.extend({_doReset:function(){var e=this._key.words,t=this.cfg.iv,r=this._X=[e[0],e[3]<<16|e[2]>>>16,e[1],e[0]<<16|e[3]>>>16,e[2],e[1]<<16|e[0]>>>16,e[3],e[2]<<16|e[1]>>>16],n=this._C=[e[2]<<16|e[2]>>>16,4294901760&e[0]|65535&e[1],e[3]<<16|e[3]>>>16,4294901760&e[1]|65535&e[2],e[0]<<16|e[0]>>>16,4294901760&e[2]|65535&e[3],e[1]<<16|e[1]>>>16,4294901760&e[3]|65535&e[0]];this._b=0;for(var i=0;i<4;i++)h.call(this);for(i=0;i<8;i++)n[i]^=r[i+4&7];if(t){var o=t.words,a=o[0],s=o[1],l=16711935&(a<<8|a>>>24)|4278255360&(a<<24|a>>>8),f=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),c=l>>>16|4294901760&f,u=f<<16|65535&l;for(n[0]^=l,n[1]^=c,n[2]^=f,n[3]^=u,n[4]^=l,n[5]^=c,n[6]^=f,n[7]^=u,i=0;i<4;i++)h.call(this)}},_doProcessBlock:function(e,t){var r=this._X;h.call(this),i[0]=r[0]^r[5]>>>16^r[3]<<16,i[1]=r[2]^r[7]>>>16^r[5]<<16,i[2]=r[4]^r[1]>>>16^r[7]<<16,i[3]=r[6]^r[3]>>>16^r[1]<<16;for(var n=0;n<4;n++)i[n]=16711935&(i[n]<<8|i[n]>>>24)|4278255360&(i[n]<<24|i[n]>>>8),e[t+n]^=i[n]},blockSize:4,ivSize:2});function h(){for(var e=this._X,t=this._C,r=0;r<8;r++)o[r]=t[r];for(t[0]=t[0]+1295307597+this._b|0,t[1]=t[1]+3545052371+(t[0]>>>0<o[0]>>>0?1:0)|0,t[2]=t[2]+886263092+(t[1]>>>0<o[1]>>>0?1:0)|0,t[3]=t[3]+1295307597+(t[2]>>>0<o[2]>>>0?1:0)|0,t[4]=t[4]+3545052371+(t[3]>>>0<o[3]>>>0?1:0)|0,t[5]=t[5]+886263092+(t[4]>>>0<o[4]>>>0?1:0)|0,t[6]=t[6]+1295307597+(t[5]>>>0<o[5]>>>0?1:0)|0,t[7]=t[7]+3545052371+(t[6]>>>0<o[6]>>>0?1:0)|0,this._b=t[7]>>>0<o[7]>>>0?1:0,r=0;r<8;r++){var n=e[r]+t[r],i=65535&n,s=n>>>16,h=((i*i>>>17)+i*s>>>15)+s*s,l=((4294901760&n)*n|0)+((65535&n)*n|0);a[r]=h^l}e[0]=a[0]+(a[7]<<16|a[7]>>>16)+(a[6]<<16|a[6]>>>16)|0,e[1]=a[1]+(a[0]<<8|a[0]>>>24)+a[7]|0,e[2]=a[2]+(a[1]<<16|a[1]>>>16)+(a[0]<<16|a[0]>>>16)|0,e[3]=a[3]+(a[2]<<8|a[2]>>>24)+a[1]|0,e[4]=a[4]+(a[3]<<16|a[3]>>>16)+(a[2]<<16|a[2]>>>16)|0,e[5]=a[5]+(a[4]<<8|a[4]>>>24)+a[3]|0,e[6]=a[6]+(a[5]<<16|a[5]>>>16)+(a[4]<<16|a[4]>>>16)|0,e[7]=a[7]+(a[6]<<8|a[6]>>>24)+a[5]|0}e.RabbitLegacy=t._createHelper(s)}(),r.RabbitLegacy)}),Q(function(e,t){e.exports=ee}));function re(){throw new Error("setTimeout has not been defined")}function ne(){throw new Error("clearTimeout has not been defined")}var ie=re,oe=ne;function ae(e){if(ie===setTimeout)return setTimeout(e,0);if((ie===re||!ie)&&setTimeout)return ie=setTimeout,setTimeout(e,0);try{return ie(e,0)}catch(t){try{return ie.call(null,e,0)}catch(t){return ie.call(this,e,0)}}}"function"==typeof e.setTimeout&&(ie=setTimeout),"function"==typeof e.clearTimeout&&(oe=clearTimeout);var se,he=[],le=!1,fe=-1;function ce(){le&&se&&(le=!1,se.length?he=se.concat(he):fe=-1,he.length&&ue())}function ue(){if(!le){var e=ae(ce);le=!0;for(var t=he.length;t;){for(se=he,he=[];++fe<t;)se&&se[fe].run();fe=-1,t=he.length}se=null,le=!1,function(e){if(oe===clearTimeout)return clearTimeout(e);if((oe===ne||!oe)&&clearTimeout)return oe=clearTimeout,clearTimeout(e);try{oe(e)}catch(t){try{return oe.call(null,e)}catch(t){return oe.call(this,e)}}}(e)}}function de(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)t[r-1]=arguments[r];he.push(new pe(e,t)),1!==he.length||le||ae(ue)}function pe(e,t){this.fun=e,this.array=t}pe.prototype.run=function(){this.fun.apply(null,this.array)};var _e=e.performance||{};_e.now||_e.mozNow||_e.msNow||_e.oNow||_e.webkitNow;function ge(){}function ve(){ve.init.call(this)}function we(e){return void 0===e._maxListeners?ve.defaultMaxListeners:e._maxListeners}function be(e,t,r){if(t)e.call(r);else for(var n=e.length,i=Ae(e,n),o=0;o<n;++o)i[o].call(r)}function ye(e,t,r,n){if(t)e.call(r,n);else for(var i=e.length,o=Ae(e,i),a=0;a<i;++a)o[a].call(r,n)}function me(e,t,r,n,i){if(t)e.call(r,n,i);else for(var o=e.length,a=Ae(e,o),s=0;s<o;++s)a[s].call(r,n,i)}function ke(e,t,r,n,i,o){if(t)e.call(r,n,i,o);else for(var a=e.length,s=Ae(e,a),h=0;h<a;++h)s[h].call(r,n,i,o)}function Ee(e,t,r,n){if(t)e.apply(r,n);else for(var i=e.length,o=Ae(e,i),a=0;a<i;++a)o[a].apply(r,n)}function Se(e,t,r,n){var i,o,a,s;if("function"!=typeof r)throw new TypeError('"listener" argument must be a function');if((o=e._events)?(o.newListener&&(e.emit("newListener",t,r.listener?r.listener:r),o=e._events),a=o[t]):(o=e._events=new ge,e._eventsCount=0),a){if("function"==typeof a?a=o[t]=n?[r,a]:[a,r]:n?a.unshift(r):a.push(r),!a.warned&&(i=we(e))&&i>0&&a.length>i){a.warned=!0;var h=new Error("Possible EventEmitter memory leak detected. "+a.length+" "+t+" listeners added. Use emitter.setMaxListeners() to increase limit");h.name="MaxListenersExceededWarning",h.emitter=e,h.type=t,h.count=a.length,s=h,"function"==typeof console.warn?console.warn(s):console.log(s)}}else a=o[t]=r,++e._eventsCount;return e}function xe(e,t,r){var n=!1;function i(){e.removeListener(t,i),n||(n=!0,r.apply(e,arguments))}return i.listener=r,i}function Re(e){var t=this._events;if(t){var r=t[e];if("function"==typeof r)return 1;if(r)return r.length}return 0}function Ae(e,t){for(var r=new Array(t);t--;)r[t]=e[t];return r}ge.prototype=Object.create(null),ve.EventEmitter=ve,ve.usingDomains=!1,ve.prototype.domain=void 0,ve.prototype._events=void 0,ve.prototype._maxListeners=void 0,ve.defaultMaxListeners=10,ve.init=function(){this.domain=null,ve.usingDomains&&(void 0).active&&(void 0).Domain,this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=new ge,this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},ve.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||isNaN(e))throw new TypeError('"n" argument must be a positive number');return this._maxListeners=e,this},ve.prototype.getMaxListeners=function(){return we(this)},ve.prototype.emit=function(e){var t,r,n,i,o,a,s,h="error"===e;if(a=this._events)h=h&&null==a.error;else if(!h)return!1;if(s=this.domain,h){if(t=arguments[1],!s){if(t instanceof Error)throw t;var l=new Error('Uncaught, unspecified "error" event. ('+t+")");throw l.context=t,l}return t||(t=new Error('Uncaught, unspecified "error" event')),t.domainEmitter=this,t.domain=s,t.domainThrown=!1,s.emit("error",t),!1}if(!(r=a[e]))return!1;var f="function"==typeof r;switch(n=arguments.length){case 1:be(r,f,this);break;case 2:ye(r,f,this,arguments[1]);break;case 3:me(r,f,this,arguments[1],arguments[2]);break;case 4:ke(r,f,this,arguments[1],arguments[2],arguments[3]);break;default:for(i=new Array(n-1),o=1;o<n;o++)i[o-1]=arguments[o];Ee(r,f,this,i)}return!0},ve.prototype.addListener=function(e,t){return Se(this,e,t,!1)},ve.prototype.on=ve.prototype.addListener,ve.prototype.prependListener=function(e,t){return Se(this,e,t,!0)},ve.prototype.once=function(e,t){if("function"!=typeof t)throw new TypeError('"listener" argument must be a function');return this.on(e,xe(this,e,t)),this},ve.prototype.prependOnceListener=function(e,t){if("function"!=typeof t)throw new TypeError('"listener" argument must be a function');return this.prependListener(e,xe(this,e,t)),this},ve.prototype.removeListener=function(e,t){var r,n,i,o,a;if("function"!=typeof t)throw new TypeError('"listener" argument must be a function');if(!(n=this._events))return this;if(!(r=n[e]))return this;if(r===t||r.listener&&r.listener===t)0==--this._eventsCount?this._events=new ge:(delete n[e],n.removeListener&&this.emit("removeListener",e,r.listener||t));else if("function"!=typeof r){for(i=-1,o=r.length;o-- >0;)if(r[o]===t||r[o].listener&&r[o].listener===t){a=r[o].listener,i=o;break}if(i<0)return this;if(1===r.length){if(r[0]=void 0,0==--this._eventsCount)return this._events=new ge,this;delete n[e]}else!function(e,t){for(var r=t,n=r+1,i=e.length;n<i;r+=1,n+=1)e[r]=e[n];e.pop()}(r,i);n.removeListener&&this.emit("removeListener",e,a||t)}return this},ve.prototype.removeAllListeners=function(e){var t,r;if(!(r=this._events))return this;if(!r.removeListener)return 0===arguments.length?(this._events=new ge,this._eventsCount=0):r[e]&&(0==--this._eventsCount?this._events=new ge:delete r[e]),this;if(0===arguments.length){for(var n,i=Object.keys(r),o=0;o<i.length;++o)"removeListener"!==(n=i[o])&&this.removeAllListeners(n);return this.removeAllListeners("removeListener"),this._events=new ge,this._eventsCount=0,this}if("function"==typeof(t=r[e]))this.removeListener(e,t);else if(t)do{this.removeListener(e,t[t.length-1])}while(t[0]);return this},ve.prototype.listeners=function(e){var t,r=this._events;return r&&(t=r[e])?"function"==typeof t?[t.listener||t]:function(e){for(var t=new Array(e.length),r=0;r<t.length;++r)t[r]=e[r].listener||e[r];return t}(t):[]},ve.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):Re.call(e,t)},ve.prototype.listenerCount=Re,ve.prototype.eventNames=function(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]};var Be="function"==typeof Object.create?function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:function(e,t){e.super_=t;var r=function(){};r.prototype=t.prototype,e.prototype=new r,e.prototype.constructor=e},ze=/%[sdj%]/g;function Le(e){if(!Ze(e)){for(var t=[],r=0;r<arguments.length;r++)t.push(De(arguments[r]));return t.join(" ")}r=1;for(var n=arguments,i=n.length,o=String(e).replace(ze,function(e){if("%%"===e)return"%";if(r>=i)return e;switch(e){case"%s":return String(n[r++]);case"%d":return Number(n[r++]);case"%j":try{return JSON.stringify(n[r++])}catch(e){return"[Circular]"}default:return e}}),a=n[r];r<i;a=n[++r])Ne(a)||!Ye(a)?o+=" "+a:o+=" "+De(a);return o}function Te(t,r){if(je(e.process))return function(){return Te(t,r).apply(this,arguments)};var n=!1;return function(){return n||(console.error(r),n=!0),t.apply(this,arguments)}}var Me,Ce={};function De(e,t){var r={seen:[],stylize:Pe};return arguments.length>=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),Fe(t)?r.showHidden=t:t&&function(e,t){if(!t||!Ye(t))return e;var r=Object.keys(t),n=r.length;for(;n--;)e[r[n]]=t[r[n]]}(r,t),je(r.showHidden)&&(r.showHidden=!1),je(r.depth)&&(r.depth=2),je(r.colors)&&(r.colors=!1),je(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=Ie),Oe(r,e,r.depth)}function Ie(e,t){var r=De.styles[t];return r?"["+De.colors[r][0]+"m"+e+"["+De.colors[r][1]+"m":e}function Pe(e,t){return e}function Oe(e,t,r){if(e.customInspect&&t&&qe(t.inspect)&&t.inspect!==De&&(!t.constructor||t.constructor.prototype!==t)){var n=t.inspect(r,e);return Ze(n)||(n=Oe(e,n,r)),n}var i=function(e,t){if(je(t))return e.stylize("undefined","undefined");if(Ze(t)){var r="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(r,"string")}if(n=t,"number"==typeof n)return e.stylize(""+t,"number");var n;if(Fe(t))return e.stylize(""+t,"boolean");if(Ne(t))return e.stylize("null","null")}(e,t);if(i)return i;var o=Object.keys(t),a=function(e){var t={};return e.forEach(function(e,r){t[e]=!0}),t}(o);if(e.showHidden&&(o=Object.getOwnPropertyNames(t)),Xe(t)&&(o.indexOf("message")>=0||o.indexOf("description")>=0))return Ue(t);if(0===o.length){if(qe(t)){var s=t.name?": "+t.name:"";return e.stylize("[Function"+s+"]","special")}if(We(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(Ke(t))return e.stylize(Date.prototype.toString.call(t),"date");if(Xe(t))return Ue(t)}var h,l,f="",c=!1,u=["{","}"];(h=t,Array.isArray(h)&&(c=!0,u=["[","]"]),qe(t))&&(f=" [Function"+(t.name?": "+t.name:"")+"]");return We(t)&&(f=" "+RegExp.prototype.toString.call(t)),Ke(t)&&(f=" "+Date.prototype.toUTCString.call(t)),Xe(t)&&(f=" "+Ue(t)),0!==o.length||c&&0!=t.length?r<0?We(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special"):(e.seen.push(t),l=c?function(e,t,r,n,i){for(var o=[],a=0,s=t.length;a<s;++a)Ge(t,String(a))?o.push(He(e,t,r,n,String(a),!0)):o.push("");return i.forEach(function(i){i.match(/^\d+$/)||o.push(He(e,t,r,n,i,!0))}),o}(e,t,r,a,o):o.map(function(n){return He(e,t,r,a,n,c)}),e.seen.pop(),function(e,t,r){if(e.reduce(function(e,t){return t.indexOf("\n"),e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60)return r[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+r[1];return r[0]+t+" "+e.join(", ")+" "+r[1]}(l,f,u)):u[0]+f+u[1]}function Ue(e){return"["+Error.prototype.toString.call(e)+"]"}function He(e,t,r,n,i,o){var a,s,h;if((h=Object.getOwnPropertyDescriptor(t,i)||{value:t[i]}).get?s=h.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):h.set&&(s=e.stylize("[Setter]","special")),Ge(n,i)||(a="["+i+"]"),s||(e.seen.indexOf(h.value)<0?(s=Ne(r)?Oe(e,h.value,null):Oe(e,h.value,r-1)).indexOf("\n")>-1&&(s=o?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n")):s=e.stylize("[Circular]","special")),je(a)){if(o&&i.match(/^\d+$/))return s;(a=JSON.stringify(""+i)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(a=a.substr(1,a.length-2),a=e.stylize(a,"name")):(a=a.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),a=e.stylize(a,"string"))}return a+": "+s}function Fe(e){return"boolean"==typeof e}function Ne(e){return null===e}function Ze(e){return"string"==typeof e}function je(e){return void 0===e}function We(e){return Ye(e)&&"[object RegExp]"===Ve(e)}function Ye(e){return"object"==typeof e&&null!==e}function Ke(e){return Ye(e)&&"[object Date]"===Ve(e)}function Xe(e){return Ye(e)&&("[object Error]"===Ve(e)||e instanceof Error)}function qe(e){return"function"==typeof e}function Ve(e){return Object.prototype.toString.call(e)}function Ge(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function $e(){this.head=null,this.tail=null,this.length=0}De.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},De.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},$e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},$e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},$e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},$e.prototype.clear=function(){this.head=this.tail=null,this.length=0},$e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,r=""+t.data;t=t.next;)r+=e+t.data;return r},$e.prototype.concat=function(e){if(0===this.length)return p.alloc(0);if(1===this.length)return this.head.data;for(var t=p.allocUnsafe(e>>>0),r=this.head,n=0;r;)r.data.copy(t,n),n+=r.data.length,r=r.next;return t};var Je=p.isEncoding||function(e){switch(e&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function Qe(e){switch(this.encoding=(e||"utf8").toLowerCase().replace(/[-_]/,""),function(e){if(e&&!Je(e))throw new Error("Unknown encoding: "+e)}(e),this.encoding){case"utf8":this.surrogateSize=3;break;case"ucs2":case"utf16le":this.surrogateSize=2,this.detectIncompleteChar=tt;break;case"base64":this.surrogateSize=3,this.detectIncompleteChar=rt;break;default:return void(this.write=et)}this.charBuffer=new p(6),this.charReceived=0,this.charLength=0}function et(e){return e.toString(this.encoding)}function tt(e){this.charReceived=e.length%2,this.charLength=this.charReceived?2:0}function rt(e){this.charReceived=e.length%3,this.charLength=this.charReceived?3:0}Qe.prototype.write=function(e){for(var t="";this.charLength;){var r=e.length>=this.charLength-this.charReceived?this.charLength-this.charReceived:e.length;if(e.copy(this.charBuffer,this.charReceived,0,r),this.charReceived+=r,this.charReceived<this.charLength)return"";if(e=e.slice(r,e.length),!((i=(t=this.charBuffer.slice(0,this.charLength).toString(this.encoding)).charCodeAt(t.length-1))>=55296&&i<=56319)){if(this.charReceived=this.charLength=0,0===e.length)return t;break}this.charLength+=this.surrogateSize,t=""}this.detectIncompleteChar(e);var n=e.length;this.charLength&&(e.copy(this.charBuffer,0,e.length-this.charReceived,n),n-=this.charReceived);var i;n=(t+=e.toString(this.encoding,0,n)).length-1;if((i=t.charCodeAt(n))>=55296&&i<=56319){var o=this.surrogateSize;return this.charLength+=o,this.charReceived+=o,this.charBuffer.copy(this.charBuffer,o,0,o),e.copy(this.charBuffer,0,0,o),t.substring(0,n)}return t},Qe.prototype.detectIncompleteChar=function(e){for(var t=e.length>=3?3:e.length;t>0;t--){var r=e[e.length-t];if(1==t&&r>>5==6){this.charLength=2;break}if(t<=2&&r>>4==14){this.charLength=3;break}if(t<=3&&r>>3==30){this.charLength=4;break}}this.charReceived=t},Qe.prototype.end=function(e){var t="";if(e&&e.length&&(t=this.write(e)),this.charReceived){var r=this.charReceived,n=this.charBuffer,i=this.encoding;t+=n.slice(0,r).toString(i)}return t},ot.ReadableState=it;var nt=function(e){je(Me)&&(Me=""),e=e.toUpperCase(),Ce[e]||(new RegExp("\\b"+e+"\\b","i").test(Me)?Ce[e]=function(){var t=Le.apply(null,arguments);console.error("%s %d: %s",e,0,t)}:Ce[e]=function(){});return Ce[e]}("stream");function it(e,t){e=e||{},this.objectMode=!!e.objectMode,t instanceof Ct&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var r=e.highWaterMark,n=this.objectMode?16:16384;this.highWaterMark=r||0===r?r:n,this.highWaterMark=~~this.highWaterMark,this.buffer=new $e,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.ranOut=!1,this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(this.decoder=new Qe(e.encoding),this.encoding=e.encoding)}function ot(e){if(!(this instanceof ot))return new ot(e);this._readableState=new it(e,this),this.readable=!0,e&&"function"==typeof e.read&&(this._read=e.read),ve.call(this)}function at(e,t,r,n,i){var o=function(e,t){var r=null;$(t)||"string"==typeof t||null==t||e.objectMode||(r=new TypeError("Invalid non-string/buffer chunk"));return r}(t,r);if(o)e.emit("error",o);else if(null===r)t.reading=!1,function(e,t){if(t.ended)return;if(t.decoder){var r=t.decoder.end();r&&r.length&&(t.buffer.push(r),t.length+=t.objectMode?1:r.length)}t.ended=!0,lt(e)}(e,t);else if(t.objectMode||r&&r.length>0)if(t.ended&&!i){var a=new Error("stream.push() after EOF");e.emit("error",a)}else if(t.endEmitted&&i){var s=new Error("stream.unshift() after end event");e.emit("error",s)}else{var h;!t.decoder||i||n||(r=t.decoder.write(r),h=!t.objectMode&&0===r.length),i||(t.reading=!1),h||(t.flowing&&0===t.length&&!t.sync?(e.emit("data",r),e.read(0)):(t.length+=t.objectMode?1:r.length,i?t.buffer.unshift(r):t.buffer.push(r),t.needReadable&<(e))),function(e,t){t.readingMore||(t.readingMore=!0,de(ct,e,t))}(e,t)}else i||(t.reading=!1);return function(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}(t)}Be(ot,ve),ot.prototype.push=function(e,t){var r=this._readableState;return r.objectMode||"string"!=typeof e||(t=t||r.defaultEncoding)!==r.encoding&&(e=p.from(e,t),t=""),at(this,r,e,t,!1)},ot.prototype.unshift=function(e){return at(this,this._readableState,e,"",!0)},ot.prototype.isPaused=function(){return!1===this._readableState.flowing},ot.prototype.setEncoding=function(e){return this._readableState.decoder=new Qe(e),this._readableState.encoding=e,this};var st=8388608;function ht(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=st?e=st:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function lt(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(nt("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?de(ft,e):ft(e))}function ft(e){nt("emit readable"),e.emit("readable"),pt(e)}function ct(e,t){for(var r=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(nt("maybeReadMore read 0"),e.read(0),r!==t.length);)r=t.length;t.readingMore=!1}function ut(e){nt("readable nexttick read 0"),e.read(0)}function dt(e,t){t.reading||(nt("resume read 0"),e.read(0)),t.resumeScheduled=!1,t.awaitDrain=0,e.emit("resume"),pt(e),t.flowing&&!t.reading&&e.read(0)}function pt(e){var t=e._readableState;for(nt("flow",t.flowing);t.flowing&&null!==e.read(););}function _t(e,t){return 0===t.length?null:(t.objectMode?r=t.buffer.shift():!e||e>=t.length?(r=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):r=function(e,t,r){var n;e<t.head.data.length?(n=t.head.data.slice(0,e),t.head.data=t.head.data.slice(e)):n=e===t.head.data.length?t.shift():r?function(e,t){var r=t.head,n=1,i=r.data;e-=i.length;for(;r=r.next;){var o=r.data,a=e>o.length?o.length:e;if(a===o.length?i+=o:i+=o.slice(0,e),0===(e-=a)){a===o.length?(++n,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=o.slice(a));break}++n}return t.length-=n,i}(e,t):function(e,t){var r=p.allocUnsafe(e),n=t.head,i=1;n.data.copy(r),e-=n.data.length;for(;n=n.next;){var o=n.data,a=e>o.length?o.length:e;if(o.copy(r,r.length-e,0,a),0===(e-=a)){a===o.length?(++i,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=o.slice(a));break}++i}return t.length-=i,r}(e,t);return n}(e,t.buffer,t.decoder),r);var r}function gt(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,de(vt,t,e))}function vt(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function wt(e,t){for(var r=0,n=e.length;r<n;r++)if(e[r]===t)return r;return-1}function bt(){}function yt(e,t,r){this.chunk=e,this.encoding=t,this.callback=r,this.next=null}function mt(e,t){Object.defineProperty(this,"buffer",{get:Te(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.")}),e=e||{},this.objectMode=!!e.objectMode,t instanceof Ct&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var r=e.highWaterMark,n=this.objectMode?16:16384;this.highWaterMark=r||0===r?r:n,this.highWaterMark=~~this.highWaterMark,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1;var i=!1===e.decodeStrings;this.decodeStrings=!i,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var r=e._writableState,n=r.sync,i=r.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(r),t)!function(e,t,r,n,i){--t.pendingcb,r?de(i,n):i(n);e._writableState.errorEmitted=!0,e.emit("error",n)}(e,r,n,t,i);else{var o=Rt(r);o||r.corked||r.bufferProcessing||!r.bufferedRequest||xt(e,r),n?de(St,e,r,o,i):St(e,r,o,i)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new zt(this)}function kt(e){if(!(this instanceof kt||this instanceof Ct))return new kt(e);this._writableState=new mt(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev)),ve.call(this)}function Et(e,t,r,n,i,o,a){t.writelen=n,t.writecb=a,t.writing=!0,t.sync=!0,r?e._writev(i,t.onwrite):e._write(i,o,t.onwrite),t.sync=!1}function St(e,t,r,n){r||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,n(),Bt(e,t)}function xt(e,t){t.bufferProcessing=!0;var r=t.bufferedRequest;if(e._writev&&r&&r.next){var n=t.bufferedRequestCount,i=new Array(n),o=t.corkedRequestsFree;o.entry=r;for(var a=0;r;)i[a]=r,r=r.next,a+=1;Et(e,t,!0,t.length,i,"",o.finish),t.pendingcb++,t.lastBufferedRequest=null,o.next?(t.corkedRequestsFree=o.next,o.next=null):t.corkedRequestsFree=new zt(t)}else{for(;r;){var s=r.chunk,h=r.encoding,l=r.callback;if(Et(e,t,!1,t.objectMode?1:s.length,s,h,l),r=r.next,t.writing)break}null===r&&(t.lastBufferedRequest=null)}t.bufferedRequestCount=0,t.bufferedRequest=r,t.bufferProcessing=!1}function Rt(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function At(e,t){t.prefinished||(t.prefinished=!0,e.emit("prefinish"))}function Bt(e,t){var r=Rt(t);return r&&(0===t.pendingcb?(At(e,t),t.finished=!0,e.emit("finish")):At(e,t)),r}function zt(e){var t=this;this.next=null,this.entry=null,this.finish=function(r){var n=t.entry;for(t.entry=null;n;){var i=n.callback;e.pendingcb--,i(r),n=n.next}e.corkedRequestsFree?e.corkedRequestsFree.next=t:e.corkedRequestsFree=t}}ot.prototype.read=function(e){nt("read",e),e=parseInt(e,10);var t=this._readableState,r=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return nt("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?gt(this):lt(this),null;if(0===(e=ht(e,t))&&t.ended)return 0===t.length&>(this),null;var n,i=t.needReadable;return nt("need readable",i),(0===t.length||t.length-e<t.highWaterMark)&&nt("length less than watermark",i=!0),t.ended||t.reading?nt("reading or ended",i=!1):i&&(nt("do read"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=ht(r,t))),null===(n=e>0?_t(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),r!==e&&t.ended&>(this)),null!==n&&this.emit("data",n),n},ot.prototype._read=function(e){this.emit("error",new Error("not implemented"))},ot.prototype.pipe=function(e,t){var r=this,n=this._readableState;switch(n.pipesCount){case 0:n.pipes=e;break;case 1:n.pipes=[n.pipes,e];break;default:n.pipes.push(e)}n.pipesCount+=1,nt("pipe count=%d opts=%j",n.pipesCount,t);var i=!t||!1!==t.end?a:l;function o(e){nt("onunpipe"),e===r&&l()}function a(){nt("onend"),e.end()}n.endEmitted?de(i):r.once("end",i),e.on("unpipe",o);var s=function(e){return function(){var t=e._readableState;nt("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&e.listeners("data").length&&(t.flowing=!0,pt(e))}}(r);e.on("drain",s);var h=!1;function l(){nt("cleanup"),e.removeListener("close",d),e.removeListener("finish",p),e.removeListener("drain",s),e.removeListener("error",u),e.removeListener("unpipe",o),r.removeListener("end",a),r.removeListener("end",l),r.removeListener("data",c),h=!0,!n.awaitDrain||e._writableState&&!e._writableState.needDrain||s()}var f=!1;function c(t){nt("ondata"),f=!1,!1!==e.write(t)||f||((1===n.pipesCount&&n.pipes===e||n.pipesCount>1&&-1!==wt(n.pipes,e))&&!h&&(nt("false write response, pause",r._readableState.awaitDrain),r._readableState.awaitDrain++,f=!0),r.pause())}function u(t){var r;nt("onerror",t),_(),e.removeListener("error",u),0===(r="error",e.listeners(r).length)&&e.emit("error",t)}function d(){e.removeListener("finish",p),_()}function p(){nt("onfinish"),e.removeListener("close",d),_()}function _(){nt("unpipe"),r.unpipe(e)}return r.on("data",c),function(e,t,r){if("function"==typeof e.prependListener)return e.prependListener(t,r);e._events&&e._events[t]?Array.isArray(e._events[t])?e._events[t].unshift(r):e._events[t]=[r,e._events[t]]:e.on(t,r)}(e,"error",u),e.once("close",d),e.once("finish",p),e.emit("pipe",r),n.flowing||(nt("pipe resume"),r.resume()),e},ot.prototype.unpipe=function(e){var t=this._readableState;if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes?this:(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this),this);if(!e){var r=t.pipes,n=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var i=0;i<n;i++)r[i].emit("unpipe",this);return this}var o=wt(t.pipes,e);return-1===o?this:(t.pipes.splice(o,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this),this)},ot.prototype.on=function(e,t){var r=ve.prototype.on.call(this,e,t);if("data"===e)!1!==this._readableState.flowing&&this.resume();else if("readable"===e){var n=this._readableState;n.endEmitted||n.readableListening||(n.readableListening=n.needReadable=!0,n.emittedReadable=!1,n.reading?n.length&<(this):de(ut,this))}return r},ot.prototype.addListener=ot.prototype.on,ot.prototype.resume=function(){var e=this._readableState;return e.flowing||(nt("resume"),e.flowing=!0,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,de(dt,e,t))}(this,e)),this},ot.prototype.pause=function(){return nt("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(nt("pause"),this._readableState.flowing=!1,this.emit("pause")),this},ot.prototype.wrap=function(e){var t=this._readableState,r=!1,n=this;for(var i in e.on("end",function(){if(nt("wrapped end"),t.decoder&&!t.ended){var e=t.decoder.end();e&&e.length&&n.push(e)}n.push(null)}),e.on("data",function(i){(nt("wrapped data"),t.decoder&&(i=t.decoder.write(i)),t.objectMode&&null==i)||(t.objectMode||i&&i.length)&&(n.push(i)||(r=!0,e.pause()))}),e)void 0===this[i]&&"function"==typeof e[i]&&(this[i]=function(t){return function(){return e[t].apply(e,arguments)}}(i));return function(e,t){for(var r=0,n=e.length;r<n;r++)t(e[r],r)}(["error","close","destroy","pause","resume"],function(t){e.on(t,n.emit.bind(n,t))}),n._read=function(t){nt("wrapped _read",t),r&&(r=!1,e.resume())},n},ot._fromList=_t,kt.WritableState=mt,Be(kt,ve),mt.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},kt.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},kt.prototype.write=function(e,t,r){var n=this._writableState,i=!1;return"function"==typeof t&&(r=t,t=null),p.isBuffer(e)?t="buffer":t||(t=n.defaultEncoding),"function"!=typeof r&&(r=bt),n.ended?function(e,t){var r=new Error("write after end");e.emit("error",r),de(t,r)}(this,r):function(e,t,r,n){var i=!0,o=!1;return null===r?o=new TypeError("May not write null values to stream"):p.isBuffer(r)||"string"==typeof r||void 0===r||t.objectMode||(o=new TypeError("Invalid non-string/buffer chunk")),o&&(e.emit("error",o),de(n,o),i=!1),i}(this,n,e,r)&&(n.pendingcb++,i=function(e,t,r,n,i){r=function(e,t,r){return e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=p.from(t,r)),t}(t,r,n),p.isBuffer(r)&&(n="buffer");var o=t.objectMode?1:r.length;t.length+=o;var a=t.length<t.highWaterMark;a||(t.needDrain=!0);if(t.writing||t.corked){var s=t.lastBufferedRequest;t.lastBufferedRequest=new yt(r,n,i),s?s.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else Et(e,t,!1,o,r,n,i);return a}(this,n,e,t,r)),i},kt.prototype.cork=function(){this._writableState.corked++},kt.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.finished||e.bufferProcessing||!e.bufferedRequest||xt(this,e))},kt.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},kt.prototype._write=function(e,t,r){r(new Error("not implemented"))},kt.prototype._writev=null,kt.prototype.end=function(e,t,r){var n=this._writableState;"function"==typeof e?(r=e,e=null,t=null):"function"==typeof t&&(r=t,t=null),null!=e&&this.write(e,t),n.corked&&(n.corked=1,this.uncork()),n.ending||n.finished||function(e,t,r){t.ending=!0,Bt(e,t),r&&(t.finished?de(r):e.once("finish",r));t.ended=!0,e.writable=!1}(this,n,r)},Be(Ct,ot);for(var Lt=Object.keys(kt.prototype),Tt=0;Tt<Lt.length;Tt++){var Mt=Lt[Tt];Ct.prototype[Mt]||(Ct.prototype[Mt]=kt.prototype[Mt])}function Ct(e){if(!(this instanceof Ct))return new Ct(e);ot.call(this,e),kt.call(this,e),e&&!1===e.readable&&(this.readable=!1),e&&!1===e.writable&&(this.writable=!1),this.allowHalfOpen=!0,e&&!1===e.allowHalfOpen&&(this.allowHalfOpen=!1),this.once("end",Dt)}function Dt(){this.allowHalfOpen||this._writableState.ended||de(It,this)}function It(e){e.end()}function Pt(e){this.afterTransform=function(t,r){return function(e,t,r){var n=e._transformState;n.transforming=!1;var i=n.writecb;if(!i)return e.emit("error",new Error("no writecb in Transform class"));n.writechunk=null,n.writecb=null,null!=r&&e.push(r);i(t);var o=e._readableState;o.reading=!1,(o.needReadable||o.length<o.highWaterMark)&&e._read(o.highWaterMark)}(e,t,r)},this.needTransform=!1,this.transforming=!1,this.writecb=null,this.writechunk=null,this.writeencoding=null}function Ot(e){if(!(this instanceof Ot))return new Ot(e);Ct.call(this,e),this._transformState=new Pt(this);var t=this;this._readableState.needReadable=!0,this._readableState.sync=!1,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.once("prefinish",function(){"function"==typeof this._flush?this._flush(function(e){Ut(t,e)}):Ut(t)})}function Ut(e,t){if(t)return e.emit("error",t);var r=e._writableState,n=e._transformState;if(r.length)throw new Error("Calling transform done when ws.length != 0");if(n.transforming)throw new Error("Calling transform done when still transforming");return e.push(null)}function Ht(e){if(!(this instanceof Ht))return new Ht(e);Ot.call(this,e)}function Ft(){ve.call(this)}Be(Ot,Ct),Ot.prototype.push=function(e,t){return this._transformState.needTransform=!1,Ct.prototype.push.call(this,e,t)},Ot.prototype._transform=function(e,t,r){throw new Error("Not implemented")},Ot.prototype._write=function(e,t,r){var n=this._transformState;if(n.writecb=r,n.writechunk=e,n.writeencoding=t,!n.transforming){var i=this._readableState;(n.needTransform||i.needReadable||i.length<i.highWaterMark)&&this._read(i.highWaterMark)}},Ot.prototype._read=function(e){var t=this._transformState;null!==t.writechunk&&t.writecb&&!t.transforming?(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform)):t.needTransform=!0},Be(Ht,Ot),Ht.prototype._transform=function(e,t,r){r(null,e)},Be(Ft,ve),Ft.Readable=ot,Ft.Writable=kt,Ft.Duplex=Ct,Ft.Transform=Ot,Ft.PassThrough=Ht,Ft.Stream=Ft,Ft.prototype.pipe=function(e,t){var r=this;function n(t){e.writable&&!1===e.write(t)&&r.pause&&r.pause()}function i(){r.readable&&r.resume&&r.resume()}r.on("data",n),e.on("drain",i),e._isStdio||t&&!1===t.end||(r.on("end",a),r.on("close",s));var o=!1;function a(){o||(o=!0,e.end())}function s(){o||(o=!0,"function"==typeof e.destroy&&e.destroy())}function h(e){if(l(),0===ve.listenerCount(this,"error"))throw e}function l(){r.removeListener("data",n),e.removeListener("drain",i),r.removeListener("end",a),r.removeListener("close",s),r.removeListener("error",h),e.removeListener("error",h),r.removeListener("end",l),r.removeListener("close",l),e.removeListener("close",l)}return r.on("error",h),e.on("error",h),r.on("end",l),r.on("close",l),e.on("close",l),e.emit("pipe",r),e};var Nt={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"};function Zt(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}function jt(e,t,r,n,i){if(t.subarray&&e.subarray)e.set(t.subarray(r,r+n),i);else for(var o=0;o<n;o++)e[i+o]=t[r+o]}var Wt=Uint8Array,Yt=Uint16Array,Kt=Int32Array,Xt=4,qt=0,Vt=1,Gt=2;function $t(e){for(var t=e.length;--t>=0;)e[t]=0}var Jt=0,Qt=1,er=2,tr=29,rr=256,nr=rr+1+tr,ir=30,or=19,ar=2*nr+1,sr=15,hr=16,lr=7,fr=256,cr=16,ur=17,dr=18,pr=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],_r=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],gr=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],vr=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],wr=new Array(2*(nr+2));$t(wr);var br=new Array(2*ir);$t(br);var yr=new Array(512);$t(yr);var mr=new Array(256);$t(mr);var kr=new Array(tr);$t(kr);var Er,Sr,xr,Rr=new Array(ir);function Ar(e,t,r,n,i){this.static_tree=e,this.extra_bits=t,this.extra_base=r,this.elems=n,this.max_length=i,this.has_stree=e&&e.length}function Br(e,t){this.dyn_tree=e,this.max_code=0,this.stat_desc=t}function zr(e){return e<256?yr[e]:yr[256+(e>>>7)]}function Lr(e,t){e.pending_buf[e.pending++]=255&t,e.pending_buf[e.pending++]=t>>>8&255}function Tr(e,t,r){e.bi_valid>hr-r?(e.bi_buf|=t<<e.bi_valid&65535,Lr(e,e.bi_buf),e.bi_buf=t>>hr-e.bi_valid,e.bi_valid+=r-hr):(e.bi_buf|=t<<e.bi_valid&65535,e.bi_valid+=r)}function Mr(e,t,r){Tr(e,r[2*t],r[2*t+1])}function Cr(e,t){var r=0;do{r|=1&e,e>>>=1,r<<=1}while(--t>0);return r>>>1}function Dr(e,t,r){var n,i,o=new Array(sr+1),a=0;for(n=1;n<=sr;n++)o[n]=a=a+r[n-1]<<1;for(i=0;i<=t;i++){var s=e[2*i+1];0!==s&&(e[2*i]=Cr(o[s]++,s))}}function Ir(e){var t;for(t=0;t<nr;t++)e.dyn_ltree[2*t]=0;for(t=0;t<ir;t++)e.dyn_dtree[2*t]=0;for(t=0;t<or;t++)e.bl_tree[2*t]=0;e.dyn_ltree[2*fr]=1,e.opt_len=e.static_len=0,e.last_lit=e.matches=0}function Pr(e){e.bi_valid>8?Lr(e,e.bi_buf):e.bi_valid>0&&(e.pending_buf[e.pending++]=e.bi_buf),e.bi_buf=0,e.bi_valid=0}function Or(e,t,r,n){var i=2*t,o=2*r;return e[i]<e[o]||e[i]===e[o]&&n[t]<=n[r]}function Ur(e,t,r){for(var n=e.heap[r],i=r<<1;i<=e.heap_len&&(i<e.heap_len&&Or(t,e.heap[i+1],e.heap[i],e.depth)&&i++,!Or(t,n,e.heap[i],e.depth));)e.heap[r]=e.heap[i],r=i,i<<=1;e.heap[r]=n}function Hr(e,t,r){var n,i,o,a,s=0;if(0!==e.last_lit)do{n=e.pending_buf[e.d_buf+2*s]<<8|e.pending_buf[e.d_buf+2*s+1],i=e.pending_buf[e.l_buf+s],s++,0===n?Mr(e,i,t):(Mr(e,(o=mr[i])+rr+1,t),0!==(a=pr[o])&&Tr(e,i-=kr[o],a),Mr(e,o=zr(--n),r),0!==(a=_r[o])&&Tr(e,n-=Rr[o],a))}while(s<e.last_lit);Mr(e,fr,t)}function Fr(e,t){var r,n,i,o=t.dyn_tree,a=t.stat_desc.static_tree,s=t.stat_desc.has_stree,h=t.stat_desc.elems,l=-1;for(e.heap_len=0,e.heap_max=ar,r=0;r<h;r++)0!==o[2*r]?(e.heap[++e.heap_len]=l=r,e.depth[r]=0):o[2*r+1]=0;for(;e.heap_len<2;)o[2*(i=e.heap[++e.heap_len]=l<2?++l:0)]=1,e.depth[i]=0,e.opt_len--,s&&(e.static_len-=a[2*i+1]);for(t.max_code=l,r=e.heap_len>>1;r>=1;r--)Ur(e,o,r);i=h;do{r=e.heap[1],e.heap[1]=e.heap[e.heap_len--],Ur(e,o,1),n=e.heap[1],e.heap[--e.heap_max]=r,e.heap[--e.heap_max]=n,o[2*i]=o[2*r]+o[2*n],e.depth[i]=(e.depth[r]>=e.depth[n]?e.depth[r]:e.depth[n])+1,o[2*r+1]=o[2*n+1]=i,e.heap[1]=i++,Ur(e,o,1)}while(e.heap_len>=2);e.heap[--e.heap_max]=e.heap[1],function(e,t){var r,n,i,o,a,s,h=t.dyn_tree,l=t.max_code,f=t.stat_desc.static_tree,c=t.stat_desc.has_stree,u=t.stat_desc.extra_bits,d=t.stat_desc.extra_base,p=t.stat_desc.max_length,_=0;for(o=0;o<=sr;o++)e.bl_count[o]=0;for(h[2*e.heap[e.heap_max]+1]=0,r=e.heap_max+1;r<ar;r++)(o=h[2*h[2*(n=e.heap[r])+1]+1]+1)>p&&(o=p,_++),h[2*n+1]=o,n>l||(e.bl_count[o]++,a=0,n>=d&&(a=u[n-d]),s=h[2*n],e.opt_len+=s*(o+a),c&&(e.static_len+=s*(f[2*n+1]+a)));if(0!==_){do{for(o=p-1;0===e.bl_count[o];)o--;e.bl_count[o]--,e.bl_count[o+1]+=2,e.bl_count[p]--,_-=2}while(_>0);for(o=p;0!==o;o--)for(n=e.bl_count[o];0!==n;)(i=e.heap[--r])>l||(h[2*i+1]!==o&&(e.opt_len+=(o-h[2*i+1])*h[2*i],h[2*i+1]=o),n--)}}(e,t),Dr(o,l,e.bl_count)}function Nr(e,t,r){var n,i,o=-1,a=t[1],s=0,h=7,l=4;for(0===a&&(h=138,l=3),t[2*(r+1)+1]=65535,n=0;n<=r;n++)i=a,a=t[2*(n+1)+1],++s<h&&i===a||(s<l?e.bl_tree[2*i]+=s:0!==i?(i!==o&&e.bl_tree[2*i]++,e.bl_tree[2*cr]++):s<=10?e.bl_tree[2*ur]++:e.bl_tree[2*dr]++,s=0,o=i,0===a?(h=138,l=3):i===a?(h=6,l=3):(h=7,l=4))}function Zr(e,t,r){var n,i,o=-1,a=t[1],s=0,h=7,l=4;for(0===a&&(h=138,l=3),n=0;n<=r;n++)if(i=a,a=t[2*(n+1)+1],!(++s<h&&i===a)){if(s<l)do{Mr(e,i,e.bl_tree)}while(0!=--s);else 0!==i?(i!==o&&(Mr(e,i,e.bl_tree),s--),Mr(e,cr,e.bl_tree),Tr(e,s-3,2)):s<=10?(Mr(e,ur,e.bl_tree),Tr(e,s-3,3)):(Mr(e,dr,e.bl_tree),Tr(e,s-11,7));s=0,o=i,0===a?(h=138,l=3):i===a?(h=6,l=3):(h=7,l=4)}}$t(Rr);var jr=!1;function Wr(e){jr||(!function(){var e,t,r,n,i,o=new Array(sr+1);for(r=0,n=0;n<tr-1;n++)for(kr[n]=r,e=0;e<1<<pr[n];e++)mr[r++]=n;for(mr[r-1]=n,i=0,n=0;n<16;n++)for(Rr[n]=i,e=0;e<1<<_r[n];e++)yr[i++]=n;for(i>>=7;n<ir;n++)for(Rr[n]=i<<7,e=0;e<1<<_r[n]-7;e++)yr[256+i++]=n;for(t=0;t<=sr;t++)o[t]=0;for(e=0;e<=143;)wr[2*e+1]=8,e++,o[8]++;for(;e<=255;)wr[2*e+1]=9,e++,o[9]++;for(;e<=279;)wr[2*e+1]=7,e++,o[7]++;for(;e<=287;)wr[2*e+1]=8,e++,o[8]++;for(Dr(wr,nr+1,o),e=0;e<ir;e++)br[2*e+1]=5,br[2*e]=Cr(e,5);Er=new Ar(wr,pr,rr+1,nr,sr),Sr=new Ar(br,_r,0,ir,sr),xr=new Ar(new Array(0),gr,0,or,lr)}(),jr=!0),e.l_desc=new Br(e.dyn_ltree,Er),e.d_desc=new Br(e.dyn_dtree,Sr),e.bl_desc=new Br(e.bl_tree,xr),e.bi_buf=0,e.bi_valid=0,Ir(e)}function Yr(e,t,r,n){Tr(e,(Jt<<1)+(n?1:0),3),function(e,t,r,n){Pr(e),n&&(Lr(e,r),Lr(e,~r)),jt(e.pending_buf,e.window,t,r,e.pending),e.pending+=r}(e,t,r,!0)}function Kr(e){Tr(e,Qt<<1,3),Mr(e,fr,wr),function(e){16===e.bi_valid?(Lr(e,e.bi_buf),e.bi_buf=0,e.bi_valid=0):e.bi_valid>=8&&(e.pending_buf[e.pending++]=255&e.bi_buf,e.bi_buf>>=8,e.bi_valid-=8)}(e)}function Xr(e,t,r,n){var i,o,a=0;e.level>0?(e.strm.data_type===Gt&&(e.strm.data_type=function(e){var t,r=4093624447;for(t=0;t<=31;t++,r>>>=1)if(1&r&&0!==e.dyn_ltree[2*t])return qt;if(0!==e.dyn_ltree[18]||0!==e.dyn_ltree[20]||0!==e.dyn_ltree[26])return Vt;for(t=32;t<rr;t++)if(0!==e.dyn_ltree[2*t])return Vt;return qt}(e)),Fr(e,e.l_desc),Fr(e,e.d_desc),a=function(e){var t;for(Nr(e,e.dyn_ltree,e.l_desc.max_code),Nr(e,e.dyn_dtree,e.d_desc.max_code),Fr(e,e.bl_desc),t=or-1;t>=3&&0===e.bl_tree[2*vr[t]+1];t--);return e.opt_len+=3*(t+1)+5+5+4,t}(e),i=e.opt_len+3+7>>>3,(o=e.static_len+3+7>>>3)<=i&&(i=o)):i=o=r+5,r+4<=i&&-1!==t?Yr(e,t,r,n):e.strategy===Xt||o===i?(Tr(e,(Qt<<1)+(n?1:0),3),Hr(e,wr,br)):(Tr(e,(er<<1)+(n?1:0),3),function(e,t,r,n){var i;for(Tr(e,t-257,5),Tr(e,r-1,5),Tr(e,n-4,4),i=0;i<n;i++)Tr(e,e.bl_tree[2*vr[i]+1],3);Zr(e,e.dyn_ltree,t-1),Zr(e,e.dyn_dtree,r-1)}(e,e.l_desc.max_code+1,e.d_desc.max_code+1,a+1),Hr(e,e.dyn_ltree,e.dyn_dtree)),Ir(e),n&&Pr(e)}function qr(e,t,r){return e.pending_buf[e.d_buf+2*e.last_lit]=t>>>8&255,e.pending_buf[e.d_buf+2*e.last_lit+1]=255&t,e.pending_buf[e.l_buf+e.last_lit]=255&r,e.last_lit++,0===t?e.dyn_ltree[2*r]++:(e.matches++,t--,e.dyn_ltree[2*(mr[r]+rr+1)]++,e.dyn_dtree[2*zr(t)]++),e.last_lit===e.lit_bufsize-1}function Vr(e,t,r,n){for(var i=65535&e|0,o=e>>>16&65535|0,a=0;0!==r;){r-=a=r>2e3?2e3:r;do{o=o+(i=i+t[n++]|0)|0}while(--a);i%=65521,o%=65521}return i|o<<16|0}var Gr=function(){for(var e,t=[],r=0;r<256;r++){e=r;for(var n=0;n<8;n++)e=1&e?3988292384^e>>>1:e>>>1;t[r]=e}return t}();function $r(e,t,r,n){var i=Gr,o=n+r;e^=-1;for(var a=n;a<o;a++)e=e>>>8^i[255&(e^t[a])];return-1^e}var Jr,Qr=0,en=1,tn=3,rn=4,nn=5,on=0,an=1,sn=-2,hn=-3,ln=-5,fn=-1,cn=1,un=2,dn=3,pn=4,_n=2,gn=8,vn=9,wn=286,bn=30,yn=19,mn=2*wn+1,kn=15,En=3,Sn=258,xn=Sn+En+1,Rn=32,An=42,Bn=69,zn=73,Ln=91,Tn=103,Mn=113,Cn=666,Dn=1,In=2,Pn=3,On=4,Un=3;function Hn(e,t){return e.msg=Nt[t],t}function Fn(e){return(e<<1)-(e>4?9:0)}function Nn(e){for(var t=e.length;--t>=0;)e[t]=0}function Zn(e){var t=e.state,r=t.pending;r>e.avail_out&&(r=e.avail_out),0!==r&&(jt(e.output,t.pending_buf,t.pending_out,r,e.next_out),e.next_out+=r,t.pending_out+=r,e.total_out+=r,e.avail_out-=r,t.pending-=r,0===t.pending&&(t.pending_out=0))}function jn(e,t){Xr(e,e.block_start>=0?e.block_start:-1,e.strstart-e.block_start,t),e.block_start=e.strstart,Zn(e.strm)}function Wn(e,t){e.pending_buf[e.pending++]=t}function Yn(e,t){e.pending_buf[e.pending++]=t>>>8&255,e.pending_buf[e.pending++]=255&t}function Kn(e,t){var r,n,i=e.max_chain_length,o=e.strstart,a=e.prev_length,s=e.nice_match,h=e.strstart>e.w_size-xn?e.strstart-(e.w_size-xn):0,l=e.window,f=e.w_mask,c=e.prev,u=e.strstart+Sn,d=l[o+a-1],p=l[o+a];e.prev_length>=e.good_match&&(i>>=2),s>e.lookahead&&(s=e.lookahead);do{if(l[(r=t)+a]===p&&l[r+a-1]===d&&l[r]===l[o]&&l[++r]===l[o+1]){o+=2,r++;do{}while(l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&l[++o]===l[++r]&&o<u);if(n=Sn-(u-o),o=u-Sn,n>a){if(e.match_start=t,a=n,n>=s)break;d=l[o+a-1],p=l[o+a]}}}while((t=c[t&f])>h&&0!=--i);return a<=e.lookahead?a:e.lookahead}function Xn(e){var t,r,n,i,o,a,s,h,l,f,c=e.w_size;do{if(i=e.window_size-e.lookahead-e.strstart,e.strstart>=c+(c-xn)){jt(e.window,e.window,c,c,0),e.match_start-=c,e.strstart-=c,e.block_start-=c,t=r=e.hash_size;do{n=e.head[--t],e.head[t]=n>=c?n-c:0}while(--r);t=r=c;do{n=e.prev[--t],e.prev[t]=n>=c?n-c:0}while(--r);i+=c}if(0===e.strm.avail_in)break;if(a=e.strm,s=e.window,h=e.strstart+e.lookahead,l=i,f=void 0,(f=a.avail_in)>l&&(f=l),r=0===f?0:(a.avail_in-=f,jt(s,a.input,a.next_in,f,h),1===a.state.wrap?a.adler=Vr(a.adler,s,f,h):2===a.state.wrap&&(a.adler=$r(a.adler,s,f,h)),a.next_in+=f,a.total_in+=f,f),e.lookahead+=r,e.lookahead+e.insert>=En)for(o=e.strstart-e.insert,e.ins_h=e.window[o],e.ins_h=(e.ins_h<<e.hash_shift^e.window[o+1])&e.hash_mask;e.insert&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[o+En-1])&e.hash_mask,e.prev[o&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=o,o++,e.insert--,!(e.lookahead+e.insert<En)););}while(e.lookahead<xn&&0!==e.strm.avail_in)}function qn(e,t){for(var r,n;;){if(e.lookahead<xn){if(Xn(e),e.lookahead<xn&&t===Qr)return Dn;if(0===e.lookahead)break}if(r=0,e.lookahead>=En&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+En-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),0!==r&&e.strstart-r<=e.w_size-xn&&(e.match_length=Kn(e,r)),e.match_length>=En)if(n=qr(e,e.strstart-e.match_start,e.match_length-En),e.lookahead-=e.match_length,e.match_length<=e.max_lazy_match&&e.lookahead>=En){e.match_length--;do{e.strstart++,e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+En-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart}while(0!=--e.match_length);e.strstart++}else e.strstart+=e.match_length,e.match_length=0,e.ins_h=e.window[e.strstart],e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+1])&e.hash_mask;else n=qr(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++;if(n&&(jn(e,!1),0===e.strm.avail_out))return Dn}return e.insert=e.strstart<En-1?e.strstart:En-1,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):e.last_lit&&(jn(e,!1),0===e.strm.avail_out)?Dn:In}function Vn(e,t){for(var r,n,i;;){if(e.lookahead<xn){if(Xn(e),e.lookahead<xn&&t===Qr)return Dn;if(0===e.lookahead)break}if(r=0,e.lookahead>=En&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+En-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart),e.prev_length=e.match_length,e.prev_match=e.match_start,e.match_length=En-1,0!==r&&e.prev_length<e.max_lazy_match&&e.strstart-r<=e.w_size-xn&&(e.match_length=Kn(e,r),e.match_length<=5&&(e.strategy===cn||e.match_length===En&&e.strstart-e.match_start>4096)&&(e.match_length=En-1)),e.prev_length>=En&&e.match_length<=e.prev_length){i=e.strstart+e.lookahead-En,n=qr(e,e.strstart-1-e.prev_match,e.prev_length-En),e.lookahead-=e.prev_length-1,e.prev_length-=2;do{++e.strstart<=i&&(e.ins_h=(e.ins_h<<e.hash_shift^e.window[e.strstart+En-1])&e.hash_mask,r=e.prev[e.strstart&e.w_mask]=e.head[e.ins_h],e.head[e.ins_h]=e.strstart)}while(0!=--e.prev_length);if(e.match_available=0,e.match_length=En-1,e.strstart++,n&&(jn(e,!1),0===e.strm.avail_out))return Dn}else if(e.match_available){if((n=qr(e,0,e.window[e.strstart-1]))&&jn(e,!1),e.strstart++,e.lookahead--,0===e.strm.avail_out)return Dn}else e.match_available=1,e.strstart++,e.lookahead--}return e.match_available&&(n=qr(e,0,e.window[e.strstart-1]),e.match_available=0),e.insert=e.strstart<En-1?e.strstart:En-1,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):e.last_lit&&(jn(e,!1),0===e.strm.avail_out)?Dn:In}function Gn(e,t,r,n,i){this.good_length=e,this.max_lazy=t,this.nice_length=r,this.max_chain=n,this.func=i}function $n(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=gn,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new Yt(2*mn),this.dyn_dtree=new Yt(2*(2*bn+1)),this.bl_tree=new Yt(2*(2*yn+1)),Nn(this.dyn_ltree),Nn(this.dyn_dtree),Nn(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new Yt(kn+1),this.heap=new Yt(2*wn+1),Nn(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new Yt(2*wn+1),Nn(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function Jn(e){var t,r=function(e){var t;return e&&e.state?(e.total_in=e.total_out=0,e.data_type=_n,(t=e.state).pending=0,t.pending_out=0,t.wrap<0&&(t.wrap=-t.wrap),t.status=t.wrap?An:Mn,e.adler=2===t.wrap?0:1,t.last_flush=Qr,Wr(t),on):Hn(e,sn)}(e);return r===on&&((t=e.state).window_size=2*t.w_size,Nn(t.head),t.max_lazy_match=Jr[t.level].max_lazy,t.good_match=Jr[t.level].good_length,t.nice_match=Jr[t.level].nice_length,t.max_chain_length=Jr[t.level].max_chain,t.strstart=0,t.block_start=0,t.lookahead=0,t.insert=0,t.match_length=t.prev_length=En-1,t.match_available=0,t.ins_h=0),r}function Qn(e,t){var r,n,i,o;if(!e||!e.state||t>nn||t<0)return e?Hn(e,sn):sn;if(n=e.state,!e.output||!e.input&&0!==e.avail_in||n.status===Cn&&t!==rn)return Hn(e,0===e.avail_out?ln:sn);if(n.strm=e,r=n.last_flush,n.last_flush=t,n.status===An)if(2===n.wrap)e.adler=0,Wn(n,31),Wn(n,139),Wn(n,8),n.gzhead?(Wn(n,(n.gzhead.text?1:0)+(n.gzhead.hcrc?2:0)+(n.gzhead.extra?4:0)+(n.gzhead.name?8:0)+(n.gzhead.comment?16:0)),Wn(n,255&n.gzhead.time),Wn(n,n.gzhead.time>>8&255),Wn(n,n.gzhead.time>>16&255),Wn(n,n.gzhead.time>>24&255),Wn(n,9===n.level?2:n.strategy>=un||n.level<2?4:0),Wn(n,255&n.gzhead.os),n.gzhead.extra&&n.gzhead.extra.length&&(Wn(n,255&n.gzhead.extra.length),Wn(n,n.gzhead.extra.length>>8&255)),n.gzhead.hcrc&&(e.adler=$r(e.adler,n.pending_buf,n.pending,0)),n.gzindex=0,n.status=Bn):(Wn(n,0),Wn(n,0),Wn(n,0),Wn(n,0),Wn(n,0),Wn(n,9===n.level?2:n.strategy>=un||n.level<2?4:0),Wn(n,Un),n.status=Mn);else{var a=gn+(n.w_bits-8<<4)<<8;a|=(n.strategy>=un||n.level<2?0:n.level<6?1:6===n.level?2:3)<<6,0!==n.strstart&&(a|=Rn),a+=31-a%31,n.status=Mn,Yn(n,a),0!==n.strstart&&(Yn(n,e.adler>>>16),Yn(n,65535&e.adler)),e.adler=1}if(n.status===Bn)if(n.gzhead.extra){for(i=n.pending;n.gzindex<(65535&n.gzhead.extra.length)&&(n.pending!==n.pending_buf_size||(n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),Zn(e),i=n.pending,n.pending!==n.pending_buf_size));)Wn(n,255&n.gzhead.extra[n.gzindex]),n.gzindex++;n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),n.gzindex===n.gzhead.extra.length&&(n.gzindex=0,n.status=zn)}else n.status=zn;if(n.status===zn)if(n.gzhead.name){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),Zn(e),i=n.pending,n.pending===n.pending_buf_size)){o=1;break}o=n.gzindex<n.gzhead.name.length?255&n.gzhead.name.charCodeAt(n.gzindex++):0,Wn(n,o)}while(0!==o);n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),0===o&&(n.gzindex=0,n.status=Ln)}else n.status=Ln;if(n.status===Ln)if(n.gzhead.comment){i=n.pending;do{if(n.pending===n.pending_buf_size&&(n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),Zn(e),i=n.pending,n.pending===n.pending_buf_size)){o=1;break}o=n.gzindex<n.gzhead.comment.length?255&n.gzhead.comment.charCodeAt(n.gzindex++):0,Wn(n,o)}while(0!==o);n.gzhead.hcrc&&n.pending>i&&(e.adler=$r(e.adler,n.pending_buf,n.pending-i,i)),0===o&&(n.status=Tn)}else n.status=Tn;if(n.status===Tn&&(n.gzhead.hcrc?(n.pending+2>n.pending_buf_size&&Zn(e),n.pending+2<=n.pending_buf_size&&(Wn(n,255&e.adler),Wn(n,e.adler>>8&255),e.adler=0,n.status=Mn)):n.status=Mn),0!==n.pending){if(Zn(e),0===e.avail_out)return n.last_flush=-1,on}else if(0===e.avail_in&&Fn(t)<=Fn(r)&&t!==rn)return Hn(e,ln);if(n.status===Cn&&0!==e.avail_in)return Hn(e,ln);if(0!==e.avail_in||0!==n.lookahead||t!==Qr&&n.status!==Cn){var s=n.strategy===un?function(e,t){for(var r;;){if(0===e.lookahead&&(Xn(e),0===e.lookahead)){if(t===Qr)return Dn;break}if(e.match_length=0,r=qr(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++,r&&(jn(e,!1),0===e.strm.avail_out))return Dn}return e.insert=0,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):e.last_lit&&(jn(e,!1),0===e.strm.avail_out)?Dn:In}(n,t):n.strategy===dn?function(e,t){for(var r,n,i,o,a=e.window;;){if(e.lookahead<=Sn){if(Xn(e),e.lookahead<=Sn&&t===Qr)return Dn;if(0===e.lookahead)break}if(e.match_length=0,e.lookahead>=En&&e.strstart>0&&(n=a[i=e.strstart-1])===a[++i]&&n===a[++i]&&n===a[++i]){o=e.strstart+Sn;do{}while(n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&n===a[++i]&&i<o);e.match_length=Sn-(o-i),e.match_length>e.lookahead&&(e.match_length=e.lookahead)}if(e.match_length>=En?(r=qr(e,1,e.match_length-En),e.lookahead-=e.match_length,e.strstart+=e.match_length,e.match_length=0):(r=qr(e,0,e.window[e.strstart]),e.lookahead--,e.strstart++),r&&(jn(e,!1),0===e.strm.avail_out))return Dn}return e.insert=0,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):e.last_lit&&(jn(e,!1),0===e.strm.avail_out)?Dn:In}(n,t):Jr[n.level].func(n,t);if(s!==Pn&&s!==On||(n.status=Cn),s===Dn||s===Pn)return 0===e.avail_out&&(n.last_flush=-1),on;if(s===In&&(t===en?Kr(n):t!==nn&&(Yr(n,0,0,!1),t===tn&&(Nn(n.head),0===n.lookahead&&(n.strstart=0,n.block_start=0,n.insert=0))),Zn(e),0===e.avail_out))return n.last_flush=-1,on}return t!==rn?on:n.wrap<=0?an:(2===n.wrap?(Wn(n,255&e.adler),Wn(n,e.adler>>8&255),Wn(n,e.adler>>16&255),Wn(n,e.adler>>24&255),Wn(n,255&e.total_in),Wn(n,e.total_in>>8&255),Wn(n,e.total_in>>16&255),Wn(n,e.total_in>>24&255)):(Yn(n,e.adler>>>16),Yn(n,65535&e.adler)),Zn(e),n.wrap>0&&(n.wrap=-n.wrap),0!==n.pending?on:an)}Jr=[new Gn(0,0,0,0,function(e,t){var r=65535;for(r>e.pending_buf_size-5&&(r=e.pending_buf_size-5);;){if(e.lookahead<=1){if(Xn(e),0===e.lookahead&&t===Qr)return Dn;if(0===e.lookahead)break}e.strstart+=e.lookahead,e.lookahead=0;var n=e.block_start+r;if((0===e.strstart||e.strstart>=n)&&(e.lookahead=e.strstart-n,e.strstart=n,jn(e,!1),0===e.strm.avail_out))return Dn;if(e.strstart-e.block_start>=e.w_size-xn&&(jn(e,!1),0===e.strm.avail_out))return Dn}return e.insert=0,t===rn?(jn(e,!0),0===e.strm.avail_out?Pn:On):(e.strstart>e.block_start&&(jn(e,!1),e.strm.avail_out),Dn)}),new Gn(4,4,8,4,qn),new Gn(4,5,16,8,qn),new Gn(4,6,32,32,qn),new Gn(4,4,16,16,Vn),new Gn(8,16,32,32,Vn),new Gn(8,16,128,128,Vn),new Gn(8,32,128,256,Vn),new Gn(32,128,258,1024,Vn),new Gn(32,258,258,4096,Vn)];var ei=30,ti=12;function ri(e,t){var r,n,i,o,a,s,h,l,f,c,u,d,p,_,g,v,w,b,y,m,k,E,S,x,R;r=e.state,n=e.next_in,x=e.input,i=n+(e.avail_in-5),o=e.next_out,R=e.output,a=o-(t-e.avail_out),s=o+(e.avail_out-257),h=r.dmax,l=r.wsize,f=r.whave,c=r.wnext,u=r.window,d=r.hold,p=r.bits,_=r.lencode,g=r.distcode,v=(1<<r.lenbits)-1,w=(1<<r.distbits)-1;e:do{p<15&&(d+=x[n++]<<p,p+=8,d+=x[n++]<<p,p+=8),b=_[d&v];t:for(;;){if(d>>>=y=b>>>24,p-=y,0===(y=b>>>16&255))R[o++]=65535&b;else{if(!(16&y)){if(0==(64&y)){b=_[(65535&b)+(d&(1<<y)-1)];continue t}if(32&y){r.mode=ti;break e}e.msg="invalid literal/length code",r.mode=ei;break e}m=65535&b,(y&=15)&&(p<y&&(d+=x[n++]<<p,p+=8),m+=d&(1<<y)-1,d>>>=y,p-=y),p<15&&(d+=x[n++]<<p,p+=8,d+=x[n++]<<p,p+=8),b=g[d&w];r:for(;;){if(d>>>=y=b>>>24,p-=y,!(16&(y=b>>>16&255))){if(0==(64&y)){b=g[(65535&b)+(d&(1<<y)-1)];continue r}e.msg="invalid distance code",r.mode=ei;break e}if(k=65535&b,p<(y&=15)&&(d+=x[n++]<<p,(p+=8)<y&&(d+=x[n++]<<p,p+=8)),(k+=d&(1<<y)-1)>h){e.msg="invalid distance too far back",r.mode=ei;break e}if(d>>>=y,p-=y,k>(y=o-a)){if((y=k-y)>f&&r.sane){e.msg="invalid distance too far back",r.mode=ei;break e}if(E=0,S=u,0===c){if(E+=l-y,y<m){m-=y;do{R[o++]=u[E++]}while(--y);E=o-k,S=R}}else if(c<y){if(E+=l+c-y,(y-=c)<m){m-=y;do{R[o++]=u[E++]}while(--y);if(E=0,c<m){m-=y=c;do{R[o++]=u[E++]}while(--y);E=o-k,S=R}}}else if(E+=c-y,y<m){m-=y;do{R[o++]=u[E++]}while(--y);E=o-k,S=R}for(;m>2;)R[o++]=S[E++],R[o++]=S[E++],R[o++]=S[E++],m-=3;m&&(R[o++]=S[E++],m>1&&(R[o++]=S[E++]))}else{E=o-k;do{R[o++]=R[E++],R[o++]=R[E++],R[o++]=R[E++],m-=3}while(m>2);m&&(R[o++]=R[E++],m>1&&(R[o++]=R[E++]))}break}}break}}while(n<i&&o<s);n-=m=p>>3,d&=(1<<(p-=m<<3))-1,e.next_in=n,e.next_out=o,e.avail_in=n<i?i-n+5:5-(n-i),e.avail_out=o<s?s-o+257:257-(o-s),r.hold=d,r.bits=p}var ni=15,ii=852,oi=592,ai=0,si=1,hi=2,li=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],fi=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],ci=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],ui=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];function di(e,t,r,n,i,o,a,s){var h,l,f,c,u,d,p,_,g,v=s.bits,w=0,b=0,y=0,m=0,k=0,E=0,S=0,x=0,R=0,A=0,B=null,z=0,L=new Yt(ni+1),T=new Yt(ni+1),M=null,C=0;for(w=0;w<=ni;w++)L[w]=0;for(b=0;b<n;b++)L[t[r+b]]++;for(k=v,m=ni;m>=1&&0===L[m];m--);if(k>m&&(k=m),0===m)return i[o++]=20971520,i[o++]=20971520,s.bits=1,0;for(y=1;y<m&&0===L[y];y++);for(k<y&&(k=y),x=1,w=1;w<=ni;w++)if(x<<=1,(x-=L[w])<0)return-1;if(x>0&&(e===ai||1!==m))return-1;for(T[1]=0,w=1;w<ni;w++)T[w+1]=T[w]+L[w];for(b=0;b<n;b++)0!==t[r+b]&&(a[T[t[r+b]]++]=b);if(e===ai?(B=M=a,d=19):e===si?(B=li,z-=257,M=fi,C-=257,d=256):(B=ci,M=ui,d=-1),A=0,b=0,w=y,u=o,E=k,S=0,f=-1,c=(R=1<<k)-1,e===si&&R>ii||e===hi&&R>oi)return 1;for(;;){p=w-S,a[b]<d?(_=0,g=a[b]):a[b]>d?(_=M[C+a[b]],g=B[z+a[b]]):(_=96,g=0),h=1<<w-S,y=l=1<<E;do{i[u+(A>>S)+(l-=h)]=p<<24|_<<16|g|0}while(0!==l);for(h=1<<w-1;A&h;)h>>=1;if(0!==h?(A&=h-1,A+=h):A=0,b++,0==--L[w]){if(w===m)break;w=t[r+a[b]]}if(w>k&&(A&c)!==f){for(0===S&&(S=k),u+=y,x=1<<(E=w-S);E+S<m&&!((x-=L[E+S])<=0);)E++,x<<=1;if(R+=1<<E,e===si&&R>ii||e===hi&&R>oi)return 1;i[f=A&c]=k<<24|E<<16|u-o|0}}return 0!==A&&(i[u+A]=w-S<<24|64<<16|0),s.bits=k,0}var pi=0,_i=1,gi=2,vi=4,wi=5,bi=6,yi=0,mi=1,ki=2,Ei=-2,Si=-3,xi=-4,Ri=-5,Ai=8,Bi=1,zi=2,Li=3,Ti=4,Mi=5,Ci=6,Di=7,Ii=8,Pi=9,Oi=10,Ui=11,Hi=12,Fi=13,Ni=14,Zi=15,ji=16,Wi=17,Yi=18,Ki=19,Xi=20,qi=21,Vi=22,Gi=23,$i=24,Ji=25,Qi=26,eo=27,to=28,ro=29,no=30,io=31,oo=32,ao=852,so=592;function ho(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function lo(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new Yt(320),this.work=new Yt(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function fo(e){var t;return e&&e.state?((t=e.state).wsize=0,t.whave=0,t.wnext=0,function(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=Bi,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new Kt(ao),t.distcode=t.distdyn=new Kt(so),t.sane=1,t.back=-1,yi):Ei}(e)):Ei}function co(e,t){var r,n;return e?(n=new lo,e.state=n,n.window=null,(r=function(e,t){var r,n;return e&&e.state?(n=e.state,t<0?(r=0,t=-t):(r=1+(t>>4),t<48&&(t&=15)),t&&(t<8||t>15)?Ei:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=r,n.wbits=t,fo(e))):Ei}(e,t))!==yi&&(e.state=null),r):Ei}var uo,po,_o=!0;function go(e){if(_o){var t;for(uo=new Kt(512),po=new Kt(32),t=0;t<144;)e.lens[t++]=8;for(;t<256;)e.lens[t++]=9;for(;t<280;)e.lens[t++]=7;for(;t<288;)e.lens[t++]=8;for(di(_i,e.lens,0,288,uo,0,e.work,{bits:9}),t=0;t<32;)e.lens[t++]=5;di(gi,e.lens,0,32,po,0,e.work,{bits:5}),_o=!1}e.lencode=uo,e.lenbits=9,e.distcode=po,e.distbits=5}function vo(e,t){var r,n,i,o,a,s,h,l,f,c,u,d,p,_,g,v,w,b,y,m,k,E,S,x,R=0,A=new Wt(4),B=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!e||!e.state||!e.output||!e.input&&0!==e.avail_in)return Ei;(r=e.state).mode===Hi&&(r.mode=Fi),a=e.next_out,i=e.output,h=e.avail_out,o=e.next_in,n=e.input,s=e.avail_in,l=r.hold,f=r.bits,c=s,u=h,E=yi;e:for(;;)switch(r.mode){case Bi:if(0===r.wrap){r.mode=Fi;break}for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(2&r.wrap&&35615===l){r.check=0,A[0]=255&l,A[1]=l>>>8&255,r.check=$r(r.check,A,2,0),l=0,f=0,r.mode=zi;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&l)<<8)+(l>>8))%31){e.msg="incorrect header check",r.mode=no;break}if((15&l)!==Ai){e.msg="unknown compression method",r.mode=no;break}if(f-=4,k=8+(15&(l>>>=4)),0===r.wbits)r.wbits=k;else if(k>r.wbits){e.msg="invalid window size",r.mode=no;break}r.dmax=1<<k,e.adler=r.check=1,r.mode=512&l?Oi:Hi,l=0,f=0;break;case zi:for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(r.flags=l,(255&r.flags)!==Ai){e.msg="unknown compression method",r.mode=no;break}if(57344&r.flags){e.msg="unknown header flags set",r.mode=no;break}r.head&&(r.head.text=l>>8&1),512&r.flags&&(A[0]=255&l,A[1]=l>>>8&255,r.check=$r(r.check,A,2,0)),l=0,f=0,r.mode=Li;case Li:for(;f<32;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.head&&(r.head.time=l),512&r.flags&&(A[0]=255&l,A[1]=l>>>8&255,A[2]=l>>>16&255,A[3]=l>>>24&255,r.check=$r(r.check,A,4,0)),l=0,f=0,r.mode=Ti;case Ti:for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.head&&(r.head.xflags=255&l,r.head.os=l>>8),512&r.flags&&(A[0]=255&l,A[1]=l>>>8&255,r.check=$r(r.check,A,2,0)),l=0,f=0,r.mode=Mi;case Mi:if(1024&r.flags){for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.length=l,r.head&&(r.head.extra_len=l),512&r.flags&&(A[0]=255&l,A[1]=l>>>8&255,r.check=$r(r.check,A,2,0)),l=0,f=0}else r.head&&(r.head.extra=null);r.mode=Ci;case Ci:if(1024&r.flags&&((d=r.length)>s&&(d=s),d&&(r.head&&(k=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),jt(r.head.extra,n,o,d,k)),512&r.flags&&(r.check=$r(r.check,n,d,o)),s-=d,o+=d,r.length-=d),r.length))break e;r.length=0,r.mode=Di;case Di:if(2048&r.flags){if(0===s)break e;d=0;do{k=n[o+d++],r.head&&k&&r.length<65536&&(r.head.name+=String.fromCharCode(k))}while(k&&d<s);if(512&r.flags&&(r.check=$r(r.check,n,d,o)),s-=d,o+=d,k)break e}else r.head&&(r.head.name=null);r.length=0,r.mode=Ii;case Ii:if(4096&r.flags){if(0===s)break e;d=0;do{k=n[o+d++],r.head&&k&&r.length<65536&&(r.head.comment+=String.fromCharCode(k))}while(k&&d<s);if(512&r.flags&&(r.check=$r(r.check,n,d,o)),s-=d,o+=d,k)break e}else r.head&&(r.head.comment=null);r.mode=Pi;case Pi:if(512&r.flags){for(;f<16;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(l!==(65535&r.check)){e.msg="header crc mismatch",r.mode=no;break}l=0,f=0}r.head&&(r.head.hcrc=r.flags>>9&1,r.head.done=!0),e.adler=r.check=0,r.mode=Hi;break;case Oi:for(;f<32;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}e.adler=r.check=ho(l),l=0,f=0,r.mode=Ui;case Ui:if(0===r.havedict)return e.next_out=a,e.avail_out=h,e.next_in=o,e.avail_in=s,r.hold=l,r.bits=f,ki;e.adler=r.check=1,r.mode=Hi;case Hi:if(t===wi||t===bi)break e;case Fi:if(r.last){l>>>=7&f,f-=7&f,r.mode=eo;break}for(;f<3;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}switch(r.last=1&l,f-=1,3&(l>>>=1)){case 0:r.mode=Ni;break;case 1:if(go(r),r.mode=Xi,t===bi){l>>>=2,f-=2;break e}break;case 2:r.mode=Wi;break;case 3:e.msg="invalid block type",r.mode=no}l>>>=2,f-=2;break;case Ni:for(l>>>=7&f,f-=7&f;f<32;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if((65535&l)!=(l>>>16^65535)){e.msg="invalid stored block lengths",r.mode=no;break}if(r.length=65535&l,l=0,f=0,r.mode=Zi,t===bi)break e;case Zi:r.mode=ji;case ji:if(d=r.length){if(d>s&&(d=s),d>h&&(d=h),0===d)break e;jt(i,n,o,d,a),s-=d,o+=d,h-=d,a+=d,r.length-=d;break}r.mode=Hi;break;case Wi:for(;f<14;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(r.nlen=257+(31&l),l>>>=5,f-=5,r.ndist=1+(31&l),l>>>=5,f-=5,r.ncode=4+(15&l),l>>>=4,f-=4,r.nlen>286||r.ndist>30){e.msg="too many length or distance symbols",r.mode=no;break}r.have=0,r.mode=Yi;case Yi:for(;r.have<r.ncode;){for(;f<3;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.lens[B[r.have++]]=7&l,l>>>=3,f-=3}for(;r.have<19;)r.lens[B[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,S={bits:r.lenbits},E=di(pi,r.lens,0,19,r.lencode,0,r.work,S),r.lenbits=S.bits,E){e.msg="invalid code lengths set",r.mode=no;break}r.have=0,r.mode=Ki;case Ki:for(;r.have<r.nlen+r.ndist;){for(;v=(R=r.lencode[l&(1<<r.lenbits)-1])>>>16&255,w=65535&R,!((g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(w<16)l>>>=g,f-=g,r.lens[r.have++]=w;else{if(16===w){for(x=g+2;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(l>>>=g,f-=g,0===r.have){e.msg="invalid bit length repeat",r.mode=no;break}k=r.lens[r.have-1],d=3+(3&l),l>>>=2,f-=2}else if(17===w){for(x=g+3;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}f-=g,k=0,d=3+(7&(l>>>=g)),l>>>=3,f-=3}else{for(x=g+7;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}f-=g,k=0,d=11+(127&(l>>>=g)),l>>>=7,f-=7}if(r.have+d>r.nlen+r.ndist){e.msg="invalid bit length repeat",r.mode=no;break}for(;d--;)r.lens[r.have++]=k}}if(r.mode===no)break;if(0===r.lens[256]){e.msg="invalid code -- missing end-of-block",r.mode=no;break}if(r.lenbits=9,S={bits:r.lenbits},E=di(_i,r.lens,0,r.nlen,r.lencode,0,r.work,S),r.lenbits=S.bits,E){e.msg="invalid literal/lengths set",r.mode=no;break}if(r.distbits=6,r.distcode=r.distdyn,S={bits:r.distbits},E=di(gi,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,S),r.distbits=S.bits,E){e.msg="invalid distances set",r.mode=no;break}if(r.mode=Xi,t===bi)break e;case Xi:r.mode=qi;case qi:if(s>=6&&h>=258){e.next_out=a,e.avail_out=h,e.next_in=o,e.avail_in=s,r.hold=l,r.bits=f,ri(e,u),a=e.next_out,i=e.output,h=e.avail_out,o=e.next_in,n=e.input,s=e.avail_in,l=r.hold,f=r.bits,r.mode===Hi&&(r.back=-1);break}for(r.back=0;v=(R=r.lencode[l&(1<<r.lenbits)-1])>>>16&255,w=65535&R,!((g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(v&&0==(240&v)){for(b=g,y=v,m=w;v=(R=r.lencode[m+((l&(1<<b+y)-1)>>b)])>>>16&255,w=65535&R,!(b+(g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}l>>>=b,f-=b,r.back+=b}if(l>>>=g,f-=g,r.back+=g,r.length=w,0===v){r.mode=Qi;break}if(32&v){r.back=-1,r.mode=Hi;break}if(64&v){e.msg="invalid literal/length code",r.mode=no;break}r.extra=15&v,r.mode=Vi;case Vi:if(r.extra){for(x=r.extra;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.length+=l&(1<<r.extra)-1,l>>>=r.extra,f-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=Gi;case Gi:for(;v=(R=r.distcode[l&(1<<r.distbits)-1])>>>16&255,w=65535&R,!((g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(0==(240&v)){for(b=g,y=v,m=w;v=(R=r.distcode[m+((l&(1<<b+y)-1)>>b)])>>>16&255,w=65535&R,!(b+(g=R>>>24)<=f);){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}l>>>=b,f-=b,r.back+=b}if(l>>>=g,f-=g,r.back+=g,64&v){e.msg="invalid distance code",r.mode=no;break}r.offset=w,r.extra=15&v,r.mode=$i;case $i:if(r.extra){for(x=r.extra;f<x;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}r.offset+=l&(1<<r.extra)-1,l>>>=r.extra,f-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){e.msg="invalid distance too far back",r.mode=no;break}r.mode=Ji;case Ji:if(0===h)break e;if(d=u-h,r.offset>d){if((d=r.offset-d)>r.whave&&r.sane){e.msg="invalid distance too far back",r.mode=no;break}d>r.wnext?(d-=r.wnext,p=r.wsize-d):p=r.wnext-d,d>r.length&&(d=r.length),_=r.window}else _=i,p=a-r.offset,d=r.length;d>h&&(d=h),h-=d,r.length-=d;do{i[a++]=_[p++]}while(--d);0===r.length&&(r.mode=qi);break;case Qi:if(0===h)break e;i[a++]=r.length,h--,r.mode=qi;break;case eo:if(r.wrap){for(;f<32;){if(0===s)break e;s--,l|=n[o++]<<f,f+=8}if(u-=h,e.total_out+=u,r.total+=u,u&&(e.adler=r.check=r.flags?$r(r.check,i,u,a-u):Vr(r.check,i,u,a-u)),u=h,(r.flags?l:ho(l))!==r.check){e.msg="incorrect data check",r.mode=no;break}l=0,f=0}r.mode=to;case to:if(r.wrap&&r.flags){for(;f<32;){if(0===s)break e;s--,l+=n[o++]<<f,f+=8}if(l!==(4294967295&r.total)){e.msg="incorrect length check",r.mode=no;break}l=0,f=0}r.mode=ro;case ro:E=mi;break e;case no:E=Si;break e;case io:return xi;case oo:default:return Ei}return e.next_out=a,e.avail_out=h,e.next_in=o,e.avail_in=s,r.hold=l,r.bits=f,(r.wsize||u!==e.avail_out&&r.mode<no&&(r.mode<eo||t!==vi))&&function(e,t,r,n){var i,o=e.state;null===o.window&&(o.wsize=1<<o.wbits,o.wnext=0,o.whave=0,o.window=new Wt(o.wsize)),n>=o.wsize?(jt(o.window,t,r-o.wsize,o.wsize,0),o.wnext=0,o.whave=o.wsize):((i=o.wsize-o.wnext)>n&&(i=n),jt(o.window,t,r-n,i,o.wnext),(n-=i)?(jt(o.window,t,r-n,n,0),o.wnext=n,o.whave=o.wsize):(o.wnext+=i,o.wnext===o.wsize&&(o.wnext=0),o.whave<o.wsize&&(o.whave+=i)))}(e,e.output,e.next_out,u-e.avail_out),c-=e.avail_in,u-=e.avail_out,e.total_in+=c,e.total_out+=u,r.total+=u,r.wrap&&u&&(e.adler=r.check=r.flags?$r(r.check,i,u,e.next_out-u):Vr(r.check,i,u,e.next_out-u)),e.data_type=r.bits+(r.last?64:0)+(r.mode===Hi?128:0)+(r.mode===Xi||r.mode===Zi?256:0),(0===c&&0===u||t===vi)&&E===yi&&(E=Ri),E}var wo,bo=1,yo=7;function mo(e){if(e<bo||e>yo)throw new TypeError("Bad argument");this.mode=e,this.init_done=!1,this.write_in_progress=!1,this.pending_close=!1,this.windowBits=0,this.level=0,this.memLevel=0,this.strategy=0,this.dictionary=null}function ko(e,t){for(var r=0;r<e.length;r++)this[t+r]=e[r]}mo.prototype.init=function(e,t,r,n,i){var o;switch(this.windowBits=e,this.level=t,this.memLevel=r,this.strategy=n,3!==this.mode&&4!==this.mode||(this.windowBits+=16),this.mode===yo&&(this.windowBits+=32),5!==this.mode&&6!==this.mode||(this.windowBits=-this.windowBits),this.strm=new Zt,this.mode){case bo:case 3:case 5:o=function(e,t,r,n,i,o){if(!e)return sn;var a=1;if(t===fn&&(t=6),n<0?(a=0,n=-n):n>15&&(a=2,n-=16),i<1||i>vn||r!==gn||n<8||n>15||t<0||t>9||o<0||o>pn)return Hn(e,sn);8===n&&(n=9);var s=new $n;return e.state=s,s.strm=e,s.wrap=a,s.gzhead=null,s.w_bits=n,s.w_size=1<<s.w_bits,s.w_mask=s.w_size-1,s.hash_bits=i+7,s.hash_size=1<<s.hash_bits,s.hash_mask=s.hash_size-1,s.hash_shift=~~((s.hash_bits+En-1)/En),s.window=new Wt(2*s.w_size),s.head=new Yt(s.hash_size),s.prev=new Yt(s.w_size),s.lit_bufsize=1<<i+6,s.pending_buf_size=4*s.lit_bufsize,s.pending_buf=new Wt(s.pending_buf_size),s.d_buf=1*s.lit_bufsize,s.l_buf=3*s.lit_bufsize,s.level=t,s.strategy=o,s.method=r,Jn(e)}(this.strm,this.level,8,this.windowBits,this.memLevel,this.strategy);break;case 2:case 4:case 6:case yo:o=co(this.strm,this.windowBits);break;default:throw new Error("Unknown mode "+this.mode)}0===o?(this.write_in_progress=!1,this.init_done=!0):this._error(o)},mo.prototype.params=function(){throw new Error("deflateParams Not supported")},mo.prototype._writeCheck=function(){if(!this.init_done)throw new Error("write before init");if(0===this.mode)throw new Error("already finalized");if(this.write_in_progress)throw new Error("write already in progress");if(this.pending_close)throw new Error("close is pending")},mo.prototype.write=function(e,t,r,n,i,o,a){this._writeCheck(),this.write_in_progress=!0;var s=this;return de(function(){s.write_in_progress=!1;var h=s._write(e,t,r,n,i,o,a);s.callback(h[0],h[1]),s.pending_close&&s.close()}),this},mo.prototype.writeSync=function(e,t,r,n,i,o,a){return this._writeCheck(),this._write(e,t,r,n,i,o,a)},mo.prototype._write=function(e,t,r,n,i,o,a){if(this.write_in_progress=!0,0!==e&&1!==e&&2!==e&&3!==e&&4!==e&&5!==e)throw new Error("Invalid flush value");null==t&&(t=new p(0),n=0,r=0),i._set?i.set=i._set:i.set=ko;var s,h=this.strm;switch(h.avail_in=n,h.input=t,h.next_in=r,h.avail_out=a,h.output=i,h.next_out=o,this.mode){case bo:case 3:case 5:s=Qn(h,e);break;case yo:case 2:case 4:case 6:s=vo(h,e);break;default:throw new Error("Unknown mode "+this.mode)}return 1!==s&&0!==s&&this._error(s),this.write_in_progress=!1,[h.avail_in,h.avail_out]},mo.prototype.close=function(){this.write_in_progress?this.pending_close=!0:(this.pending_close=!1,this.mode===bo||3===this.mode||5===this.mode?function(e){var t;e&&e.state&&((t=e.state.status)!==An&&t!==Bn&&t!==zn&&t!==Ln&&t!==Tn&&t!==Mn&&t!==Cn?Hn(e,sn):(e.state=null,t===Mn&&Hn(e,hn)))}(this.strm):function(e){if(!e||!e.state)return Ei;var t=e.state;t.window&&(t.window=null),e.state=null}(this.strm),this.mode=0)},mo.prototype.reset=function(){switch(this.mode){case bo:case 5:wo=Jn(this.strm);break;case 2:case 6:wo=fo(this.strm)}0!==wo&&this._error(wo)},mo.prototype._error=function(e){this.onerror(Nt[e]+": "+this.strm.msg,e),this.write_in_progress=!1,this.pending_close&&this.close()};var Eo=Object.freeze({NONE:0,DEFLATE:bo,INFLATE:2,GZIP:3,GUNZIP:4,DEFLATERAW:5,INFLATERAW:6,UNZIP:yo,Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8,Zlib:mo});var So={};Object.keys(Eo).forEach(function(e){So[e]=Eo[e]}),So.Z_MIN_WINDOWBITS=8,So.Z_MAX_WINDOWBITS=15,So.Z_DEFAULT_WINDOWBITS=15,So.Z_MIN_CHUNK=64,So.Z_MAX_CHUNK=1/0,So.Z_DEFAULT_CHUNK=16384,So.Z_MIN_MEMLEVEL=1,So.Z_MAX_MEMLEVEL=9,So.Z_DEFAULT_MEMLEVEL=8,So.Z_MIN_LEVEL=-1,So.Z_MAX_LEVEL=9,So.Z_DEFAULT_LEVEL=So.Z_DEFAULT_COMPRESSION;var xo={Z_OK:So.Z_OK,Z_STREAM_END:So.Z_STREAM_END,Z_NEED_DICT:So.Z_NEED_DICT,Z_ERRNO:So.Z_ERRNO,Z_STREAM_ERROR:So.Z_STREAM_ERROR,Z_DATA_ERROR:So.Z_DATA_ERROR,Z_MEM_ERROR:So.Z_MEM_ERROR,Z_BUF_ERROR:So.Z_BUF_ERROR,Z_VERSION_ERROR:So.Z_VERSION_ERROR};function Ro(e,t,r){var n=[],i=0;function o(){for(var t;null!==(t=e.read());)n.push(t),i+=t.length;e.once("readable",o)}function a(){var t=p.concat(n,i);n=[],r(null,t),e.close()}e.on("error",function(t){e.removeListener("end",a),e.removeListener("readable",o),r(t)}),e.on("end",a),e.end(t),o()}function Ao(e,t){if("string"==typeof t&&(t=new p(t)),!$(t))throw new TypeError("Not a string or buffer");var r=So.Z_FINISH;return e._processChunk(t,r)}function Bo(e){if(!(this instanceof Bo))return new Bo(e);Io.call(this,e,So.DEFLATE)}function zo(e){if(!(this instanceof zo))return new zo(e);Io.call(this,e,So.INFLATE)}function Lo(e){if(!(this instanceof Lo))return new Lo(e);Io.call(this,e,So.GZIP)}function To(e){if(!(this instanceof To))return new To(e);Io.call(this,e,So.GUNZIP)}function Mo(e){if(!(this instanceof Mo))return new Mo(e);Io.call(this,e,So.DEFLATERAW)}function Co(e){if(!(this instanceof Co))return new Co(e);Io.call(this,e,So.INFLATERAW)}function Do(e){if(!(this instanceof Do))return new Do(e);Io.call(this,e,So.UNZIP)}function Io(e,t){if(this._opts=e=e||{},this._chunkSize=e.chunkSize||So.Z_DEFAULT_CHUNK,Ot.call(this,e),e.flush&&e.flush!==So.Z_NO_FLUSH&&e.flush!==So.Z_PARTIAL_FLUSH&&e.flush!==So.Z_SYNC_FLUSH&&e.flush!==So.Z_FULL_FLUSH&&e.flush!==So.Z_FINISH&&e.flush!==So.Z_BLOCK)throw new Error("Invalid flush flag: "+e.flush);if(this._flushFlag=e.flush||So.Z_NO_FLUSH,e.chunkSize&&(e.chunkSize<So.Z_MIN_CHUNK||e.chunkSize>So.Z_MAX_CHUNK))throw new Error("Invalid chunk size: "+e.chunkSize);if(e.windowBits&&(e.windowBits<So.Z_MIN_WINDOWBITS||e.windowBits>So.Z_MAX_WINDOWBITS))throw new Error("Invalid windowBits: "+e.windowBits);if(e.level&&(e.level<So.Z_MIN_LEVEL||e.level>So.Z_MAX_LEVEL))throw new Error("Invalid compression level: "+e.level);if(e.memLevel&&(e.memLevel<So.Z_MIN_MEMLEVEL||e.memLevel>So.Z_MAX_MEMLEVEL))throw new Error("Invalid memLevel: "+e.memLevel);if(e.strategy&&e.strategy!=So.Z_FILTERED&&e.strategy!=So.Z_HUFFMAN_ONLY&&e.strategy!=So.Z_RLE&&e.strategy!=So.Z_FIXED&&e.strategy!=So.Z_DEFAULT_STRATEGY)throw new Error("Invalid strategy: "+e.strategy);if(e.dictionary&&!$(e.dictionary))throw new Error("Invalid dictionary: it should be a Buffer instance");this._binding=new So.Zlib(t);var r=this;this._hadError=!1,this._binding.onerror=function(e,t){r._binding=null,r._hadError=!0;var n=new Error(e);n.errno=t,n.code=So.codes[t],r.emit("error",n)};var n=So.Z_DEFAULT_COMPRESSION;"number"==typeof e.level&&(n=e.level);var i=So.Z_DEFAULT_STRATEGY;"number"==typeof e.strategy&&(i=e.strategy),this._binding.init(e.windowBits||So.Z_DEFAULT_WINDOWBITS,n,e.memLevel||So.Z_DEFAULT_MEMLEVEL,i,e.dictionary),this._buffer=new p(this._chunkSize),this._offset=0,this._closed=!1,this._level=n,this._strategy=i,this.once("end",this.close)}Object.keys(xo).forEach(function(e){xo[xo[e]]=e}),Be(Io,Ot),Io.prototype.params=function(e,t,r){if(e<So.Z_MIN_LEVEL||e>So.Z_MAX_LEVEL)throw new RangeError("Invalid compression level: "+e);if(t!=So.Z_FILTERED&&t!=So.Z_HUFFMAN_ONLY&&t!=So.Z_RLE&&t!=So.Z_FIXED&&t!=So.Z_DEFAULT_STRATEGY)throw new TypeError("Invalid strategy: "+t);if(this._level!==e||this._strategy!==t){var n=this;this.flush(So.Z_SYNC_FLUSH,function(){n._binding.params(e,t),n._hadError||(n._level=e,n._strategy=t,r&&r())})}else de(r)},Io.prototype.reset=function(){return this._binding.reset()},Io.prototype._flush=function(e){this._transform(new p(0),"",e)},Io.prototype.flush=function(e,t){var r=this._writableState;if(("function"==typeof e||void 0===e&&!t)&&(t=e,e=So.Z_FULL_FLUSH),r.ended)t&&de(t);else if(r.ending)t&&this.once("end",t);else if(r.needDrain){var n=this;this.once("drain",function(){n.flush(t)})}else this._flushFlag=e,this.write(new p(0),"",t)},Io.prototype.close=function(e){if(e&&de(e),!this._closed){this._closed=!0,this._binding.close();var t=this;de(function(){t.emit("close")})}},Io.prototype._transform=function(e,t,r){var n,i=this._writableState,o=(i.ending||i.ended)&&(!e||i.length===e.length);if(null===!e&&!$(e))return r(new Error("invalid input"));o?n=So.Z_FINISH:(n=this._flushFlag,e.length>=i.length&&(this._flushFlag=this._opts.flush||So.Z_NO_FLUSH)),this._processChunk(e,n,r)},Io.prototype._processChunk=function(e,t,r){var n=e&&e.length,i=this._chunkSize-this._offset,o=0,a=this,s="function"==typeof r;if(!s){var h,l=[],f=0;this.on("error",function(e){h=e});do{var c=this._binding.writeSync(t,e,o,n,this._buffer,this._offset,i)}while(!this._hadError&&_(c[0],c[1]));if(this._hadError)throw h;var u=p.concat(l,f);return this.close(),u}var d=this._binding.write(t,e,o,n,this._buffer,this._offset,i);function _(h,c){if(!a._hadError){var u=i-c;if(function(e,t){if(!e)throw new Error(t)}(u>=0,"have should not go down"),u>0){var d=a._buffer.slice(a._offset,a._offset+u);a._offset+=u,s?a.push(d):(l.push(d),f+=d.length)}if((0===c||a._offset>=a._chunkSize)&&(i=a._chunkSize,a._offset=0,a._buffer=new p(a._chunkSize)),0===c){if(o+=n-h,n=h,!s)return!0;var g=a._binding.write(t,e,o,n,a._buffer,a._offset,a._chunkSize);return g.callback=_,void(g.buffer=e)}if(!s)return!1;r()}}d.buffer=e,d.callback=_},Be(Bo,Io),Be(zo,Io),Be(Lo,Io),Be(To,Io),Be(Mo,Io),Be(Co,Io),Be(Do,Io);var Po={codes:xo,createDeflate:function(e){return new Bo(e)},createInflate:function(e){return new zo(e)},createDeflateRaw:function(e){return new Mo(e)},createInflateRaw:function(e){return new Co(e)},createGzip:function(e){return new Lo(e)},createGunzip:function(e){return new To(e)},createUnzip:function(e){return new Do(e)},deflate:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Bo(t),e,r)},deflateSync:function(e,t){return Ao(new Bo(t),e)},gzip:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Lo(t),e,r)},gzipSync:function(e,t){return Ao(new Lo(t),e)},deflateRaw:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Mo(t),e,r)},deflateRawSync:function(e,t){return Ao(new Mo(t),e)},unzip:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Do(t),e,r)},unzipSync:function(e,t){return Ao(new Do(t),e)},inflate:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new zo(t),e,r)},inflateSync:function(e,t){return Ao(new zo(t),e)},gunzip:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new To(t),e,r)},gunzipSync:function(e,t){return Ao(new To(t),e)},inflateRaw:function(e,t,r){return"function"==typeof t&&(r=t,t={}),Ro(new Co(t),e,r)},inflateRawSync:function(e,t){return Ao(new Co(t),e)},Deflate:Bo,Inflate:zo,Gzip:Lo,Gunzip:To,DeflateRaw:Mo,InflateRaw:Co,Unzip:Do,Zlib:Io};export default class{constructor(e,t,r){this.SDKAPPID=e,this.EXPIRETIME=r,this.PRIVATEKEY=t}genTestUserSig(e){return this._isNumber(this.SDKAPPID)?this._isString(this.PRIVATEKEY)?this._isString(e)?this._isNumber(this.EXPIRETIME)?(console.log("sdkAppID="+this.SDKAPPID+" key="+this.PRIVATEKEY+" userID="+e+" expire="+this.EXPIRETIME),this.genSigWithUserbuf(e,this.EXPIRETIME,null)):(console.error("expireTime must be a number"),""):(console.error("userID must be a string"),""):(console.error("privateKey must be a string"),""):(console.error("sdkAppID must be a number"),"")}newBuffer(e,t){return p.from?p.from(e,t):new p(e,t)}unescape(e){return e.replace(/_/g,"=").replace(/\-/g,"/").replace(/\*/g,"+")}escape(e){return e.replace(/\+/g,"*").replace(/\//g,"-").replace(/=/g,"_")}encode(e){return this.escape(this.newBuffer(e).toString("base64"))}decode(e){return this.newBuffer(this.unescape(e),"base64")}base64encode(e){return this.newBuffer(e).toString("base64")}base64decode(e){return this.newBuffer(e,"base64").toString()}_hmacsha256(e,t,r,n){let i="TLS.identifier:"+e+"\n";i+="TLS.sdkappid:"+this.SDKAPPID+"\n",i+="TLS.time:"+t+"\n",i+="TLS.expire:"+r+"\n",null!=n&&(i+="TLS.userbuf:"+n+"\n");let o=te.HmacSHA256(i,this.PRIVATEKEY);return te.enc.Base64.stringify(o)}_utc(){return Math.round(Date.now()/1e3)}_isNumber(e){return null!==e&&("number"==typeof e&&!isNaN(e-0)||"object"==typeof e&&e.constructor===Number)}_isString(e){return"string"==typeof e}genSigWithUserbuf(e,t,r){let n=this._utc(),i={"TLS.ver":"2.0","TLS.identifier":e,"TLS.sdkappid":this.SDKAPPID,"TLS.time":n,"TLS.expire":t},o="";if(null!=r){let a=this.base64encode(r);i["TLS.userbuf"]=a,o=this._hmacsha256(e,n,t,a)}else o=this._hmacsha256(e,n,t,null);i["TLS.sig"]=o;let a=JSON.stringify(i),s=Po.deflateSync(this.newBuffer(a)).toString("base64"),h=this.escape(s);return console.log("ret="+h),h}validate(e){let t=this.decode(e),r=Po.inflateSync(t);console.log("validate ret="+r)}} |
| New file |
| | |
| | | export default { |
| | | extends: [ |
| | | 'stylelint-config-standard', |
| | | 'stylelint-config-standard-vue', |
| | | 'stylelint-config-recess-order', |
| | | ], |
| | | ignoreFiles: [ |
| | | 'dist/**', |
| | | 'src/uni_modules/**', |
| | | 'node_modules/**', |
| | | 'src/static/styles/theme.scss', // 忽略主题文件,因为包含 CSS 自定义属性 |
| | | ], |
| | | rules: { |
| | | // 禁止空代码 |
| | | 'no-empty-source': null, |
| | | // 禁止在覆盖高特异性选择器之后出现低特异性选择器 |
| | | 'no-descending-specificity': null, |
| | | // 不允许未知单位 |
| | | 'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }], |
| | | // 禁止空注释 |
| | | 'comment-no-empty': true, |
| | | // @import 规则必须始终使用字符串表示法。 |
| | | 'import-notation': 'string', |
| | | // 未知的 @ 规则 |
| | | 'at-rule-no-unknown': [ |
| | | true, |
| | | { |
| | | ignoreAtRules: [ |
| | | 'plugin', |
| | | 'apply', |
| | | 'screen', |
| | | 'function', |
| | | 'if', |
| | | 'each', |
| | | 'include', |
| | | 'mixin', |
| | | 'extend', |
| | | 'content', |
| | | 'use', |
| | | ], |
| | | }, |
| | | ], |
| | | 'selector-pseudo-element-no-unknown': [ |
| | | true, |
| | | { |
| | | ignorePseudoElements: ['v-deep'], |
| | | }, |
| | | ], |
| | | 'selector-pseudo-class-no-unknown': [ |
| | | true, |
| | | { |
| | | ignorePseudoClasses: ['deep'], |
| | | }, |
| | | ], |
| | | 'selector-type-no-unknown': [true, { ignoreTypes: ['page', 'radio', 'checkbox', 'scroll-view'] }], |
| | | 'at-rule-no-deprecated': null, |
| | | }, |
| | | }; |
| New file |
| | |
| | | /* |
| | | * @Author : yuan |
| | | * @Date : 2025-09-28 09:31:16 |
| | | * @LastEditors : yuan |
| | | * @LastEditTime : 2025-09-28 09:38:38 |
| | | * @FilePath : \uno.config.js |
| | | * @Description : |
| | | * Copyright 2025 OBKoro1, All Rights Reserved. |
| | | * 2025-09-28 09:31:16 |
| | | */ |
| | | import { |
| | | defineConfig, |
| | | presetIcons, |
| | | transformerDirectives, |
| | | transformerVariantGroup |
| | | } from "unocss" |
| | | import { presetWeapp } from "unocss-preset-weapp" |
| | | import { |
| | | extractorAttributify, |
| | | transformerClass |
| | | } from "unocss-preset-weapp/transformer" |
| | | |
| | | const { |
| | | presetWeappAttributify, |
| | | transformerAttributify |
| | | } = extractorAttributify() |
| | | |
| | | export default defineConfig({ |
| | | presets: [ |
| | | // https://github.com/MellowCo/unocss-preset-weapp |
| | | presetWeapp(), |
| | | presetWeappAttributify(), |
| | | // https://unocss.dev/presets/icons |
| | | presetIcons({ |
| | | scale: 1.2, |
| | | warn: true, |
| | | extraProperties: { |
| | | display: "inline-block", |
| | | "vertical-align": "middle" |
| | | } |
| | | }) |
| | | ], |
| | | /** |
| | | * 自定义快捷语句 |
| | | * @see https://github.com/unocss/unocss#shortcuts |
| | | */ |
| | | shortcuts: { |
| | | "border-base": "border border-gray-500_10", |
| | | center: "flex justify-center items-center" |
| | | }, |
| | | theme: { |
| | | colors: { |
| | | // 主题颜色 |
| | | primary: "var(--theme-primary)", |
| | | success: "var(--theme-success)", |
| | | warning: "var(--theme-warning)", |
| | | error: "var(--theme-error)", |
| | | // 文字颜色 |
| | | "text-main": "var(--theme-main-color)", |
| | | "text-content": "var(--theme-content-color)", |
| | | "text-tips": "var(--theme-tips-color)", |
| | | "text-light": "var(--theme-light-color)", |
| | | "text-disabled": "var(--theme-disabled-color)", |
| | | // 背景颜色 |
| | | "bg-main": "var(--theme-bg-color)", |
| | | "bg-secondary": "var(--theme-bg-color-secondary)", |
| | | // 边框颜色 |
| | | "border-main": "var(--theme-border-color)" |
| | | } |
| | | }, |
| | | transformers: [ |
| | | // 启用 @apply 功能 |
| | | transformerDirectives({ |
| | | enforce: "pre" |
| | | }), |
| | | // https://unocss.dev/transformers/variant-group |
| | | // 启用 () 分组功能 |
| | | transformerVariantGroup(), |
| | | transformerAttributify(), |
| | | // https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerClass |
| | | transformerClass() |
| | | ] |
| | | }) |
| New file |
| | |
| | | import process from "node:process" |
| | | import { fileURLToPath, URL } from "node:url" |
| | | import { defineConfig, loadEnv } from "vite" |
| | | import { createViteProxy } from "./build/config/index" |
| | | import createVitePlugins from "./build/plugins/index" |
| | | import configEnv from "./src/config/env.js"; |
| | | |
| | | // https://vitejs.dev/config/ |
| | | export default defineConfig(({ command, mode }) => { |
| | | // mode: 区分生产环境还是开发环境 |
| | | console.log("command, mode -> ", command, mode) |
| | | |
| | | const { UNI_PLATFORM,UNI_CUSTOM_DEFINE } = process.env |
| | | const ENV_NAME = UNI_CUSTOM_DEFINE && JSON.parse(UNI_CUSTOM_DEFINE)?.ENV_NAME |
| | | const __APP_ENV__ = { |
| | | UNI_PLATFORM: UNI_PLATFORM, |
| | | ENV_NAME: ENV_NAME || 'development' |
| | | } |
| | | console.log("平台 -> ", __APP_ENV__.UNI_PLATFORM) // 得到 mp-weixin, h5, app 等 |
| | | console.log("环境 -> ", __APP_ENV__.ENV_NAME) // 得到 development,test 等 |
| | | |
| | | const env = loadEnv(mode, fileURLToPath(new URL("./env", import.meta.url))) |
| | | // console.log("环境变量 env -> ", env) |
| | | const isBuild = process.env.NODE_ENV === "production" |
| | | return { |
| | | define: { |
| | | __APP_ENV__, |
| | | }, |
| | | // 自定义env目录 |
| | | envDir: "./env", |
| | | resolve: { |
| | | // https://cn.vitejs.dev/config/#resolve-alias |
| | | alias: { |
| | | // 设置别名 |
| | | "@": fileURLToPath(new URL("./src", import.meta.url)) |
| | | } |
| | | }, |
| | | // vite 相关配置 |
| | | server: { |
| | | port: Number.parseInt(env.VITE_APP_PORT, 10), |
| | | hmr: true, |
| | | host: true, |
| | | open: true, |
| | | proxy: createViteProxy(env,__APP_ENV__.ENV_NAME) |
| | | }, |
| | | // 设置scss的api类型为modern-compiler |
| | | css: { |
| | | preprocessorOptions: { |
| | | scss: { |
| | | api: "modern-compiler", |
| | | // 消除一些不必要的警告 |
| | | silenceDeprecations: ["legacy-js-api"] |
| | | } |
| | | } |
| | | }, |
| | | plugins: createVitePlugins(isBuild), |
| | | esbuild: { |
| | | drop: JSON.parse(env.VITE_DROP_CONSOLE) ? ["console", "debugger"] : [] |
| | | } |
| | | } |
| | | }) |