| @@ -0,0 +1,3 @@ | |||
| .vscode | |||
| node_modules | |||
| dist | |||
| @@ -0,0 +1,9 @@ | |||
| # Browsers that we support | |||
| > 1% | |||
| last 2 versions | |||
| not dead | |||
| # Node.js that we support | |||
| node >= 8.11.0 | |||
| @@ -0,0 +1,2 @@ | |||
| **/node_modules | |||
| **/dist | |||
| @@ -0,0 +1,2 @@ | |||
| NODE_ENV='development' | |||
| VUE_APP_SERVER_URL=https://localhost:8080 | |||
| @@ -0,0 +1,2 @@ | |||
| NODE_ENV='production' | |||
| VUE_APP_SERVER_URL=https://127.0.0.1 | |||
| @@ -0,0 +1,2 @@ | |||
| NODE_ENV='test' | |||
| VUE_APP_SERVER_URL=http://10.12.96.114:8082/ | |||
| @@ -0,0 +1,23 @@ | |||
| module.exports = { | |||
| root: true, | |||
| env: { | |||
| node: true | |||
| }, | |||
| extends: [ | |||
| // "eslint:recommended", | |||
| "plugin:vue/base", | |||
| "plugin:vue/essential", | |||
| "plugin:vue/strongly-recommended", | |||
| "plugin:vue/recommended", | |||
| "@vue/prettier", | |||
| "prettier/babel" | |||
| ], | |||
| parserOptions: { | |||
| parser: "babel-eslint" | |||
| }, | |||
| rules: { | |||
| "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", | |||
| "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off" | |||
| } | |||
| }; | |||
| @@ -0,0 +1,23 @@ | |||
| .DS_Store | |||
| node_modules | |||
| /dist | |||
| # local env files | |||
| .env.local | |||
| .env.*.local | |||
| # Log files | |||
| npm-debug.log* | |||
| yarn-debug.log* | |||
| yarn-error.log* | |||
| # Editor directories and files | |||
| .idea | |||
| .vscode | |||
| !.vscode/launch.json | |||
| !.vscode/settings.json | |||
| *.suo | |||
| *.ntvs* | |||
| *.njsproj | |||
| *.sln | |||
| *.sw? | |||
| @@ -0,0 +1,5 @@ | |||
| # For fix low severity vulnerability of package yargs-parser | |||
| # registry=https://registry.npmjs.org | |||
| # For speeding up jenkins compile process | |||
| registry=https://registry.npm.taobao.org | |||
| @@ -0,0 +1,10 @@ | |||
| { | |||
| "eslintIntegration": true, | |||
| "formatOnSave": false, | |||
| "tabWidth": 4, | |||
| "printWidth": 120, | |||
| "arrowParens": "always" | |||
| } | |||
| @@ -0,0 +1,7 @@ | |||
| { | |||
| "rules": { | |||
| "selector-pseudo-element-no-unknown": [true, { | |||
| "ignorePseudoElements": ["-webkit-media-controls-enclosure"] | |||
| }] | |||
| } | |||
| } | |||
| @@ -0,0 +1,12 @@ | |||
| module.exports = { | |||
| presets: ["@vue/cli-plugin-babel/preset"], | |||
| plugins: [ | |||
| [ | |||
| "component", | |||
| { | |||
| libraryName: "mint-ui", | |||
| style: true | |||
| } | |||
| ] | |||
| ] | |||
| }; | |||
| @@ -0,0 +1,96 @@ | |||
| user www-data; | |||
| worker_processes 1; | |||
| error_log /var/log/nginx/error.log warn; | |||
| pid /var/run/nginx.pid; | |||
| events { | |||
| worker_connections 1024; | |||
| } | |||
| http { | |||
| include /etc/nginx/mime.types; | |||
| default_type application/octet-stream; | |||
| log_format main '$remote_addr($http_x_real_ip) - $remote_user [$time_local] ' | |||
| '$ssl_protocol/$ssl_cipher ' | |||
| '"$http_host($http_true_client_ip:$upstream_addr) $request" $status $body_bytes_sent ' | |||
| '"$http_referer" "$http_user_agent" "$http_x_forwarded_for"' | |||
| '\n'; | |||
| access_log /var/log/nginx/access.log main; | |||
| sendfile on; | |||
| keepalive_timeout 65; | |||
| gzip on; | |||
| gzip_static on; | |||
| gzip_vary on; | |||
| gzip_disable "MSIE [1-6]\."; | |||
| gzip_proxied expired no-cache no-store private auth; | |||
| gzip_comp_level 1; | |||
| gzip_min_length 10k; | |||
| gzip_types | |||
| text/plain | |||
| text/css | |||
| text/js | |||
| text/javascript | |||
| text/html | |||
| text/xml | |||
| text/x-component | |||
| application/javascript | |||
| application/x-javascript | |||
| application/json | |||
| application/xhtml+xml | |||
| application/xml | |||
| application/rss+xml | |||
| application/x-font-ttf | |||
| application/vnd.ms-fontobject | |||
| font/truetype | |||
| font/opentype | |||
| image/svg+xml svg svgz; | |||
| map $http_accept $webp_suffix { | |||
| default ""; | |||
| "~*webp" ".webp"; | |||
| } | |||
| map $msie $cache_control { | |||
| "1" "private"; | |||
| } | |||
| map $msie $vary_header { | |||
| default "Accept"; | |||
| "1" ""; | |||
| } | |||
| server { | |||
| listen 8888 ssl http2; | |||
| listen [::]:8888 ssl http2; | |||
| server_name test.cloudminds.com; | |||
| ssl_certificate /etc/nginx/cert/214971167760195.pem; | |||
| ssl_certificate_key /etc/nginx/cert/214971167760195.key; | |||
| ssl_session_cache shared:SSL:10m; | |||
| ssl_session_timeout 10m; | |||
| ssl_protocols TLSv1 TLSv1.1 TLSv1.2; | |||
| ssl_ciphers HIGH:!aNULL:!MD5; | |||
| ssl_prefer_server_ciphers on; | |||
| location / { | |||
| root /srv/www/cloudia-fe-mall; | |||
| index index.html; | |||
| try_files $uri $uri/ /index.html; | |||
| } | |||
| location ~* .(jpe?g|png|gif|svg)$ { | |||
| root /srv/www/cloudia-fe-mall; | |||
| add_header Vary $vary_header; | |||
| add_header Cache-Control $cache_control; | |||
| try_files $uri$webp_suffix $uri =404; | |||
| } | |||
| error_page 500 502 503 504 /50x.html; | |||
| location = /50x.html { | |||
| root /usr/share/nginx/html; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,60 @@ | |||
| { | |||
| "name": "aobei-aiman", | |||
| "version": "1.0.0", | |||
| "info": "奥北数字人", | |||
| "private": true, | |||
| "scripts": { | |||
| "serve": "vue-cli-service serve --open", | |||
| "build": "vue-cli-service build --modern --mode development", | |||
| "build:test": "vue-cli-service build --modern --mode test", | |||
| "build:prod": "vue-cli-service build --modern --mode production", | |||
| "lint": "vue-cli-service lint --no-fix", | |||
| "lint:fix": "vue-cli-service lint", | |||
| "analyze": "cross-env ANALYZER=true npm run build:prod && webpack-bundle-analyzer --port 8123 dist/stats.json" | |||
| }, | |||
| "dependencies": { | |||
| "axios": "^0.19.2", | |||
| "core-js": "^3.6.4", | |||
| "element-ui": "^2.15.10", | |||
| "js-md5": "^0.7.3", | |||
| "jsencrypt": "^3.2.1", | |||
| "lodash": "^4.17.15", | |||
| "mint-ui": "^2.2.13", | |||
| "moment": "^2.29.4", | |||
| "video.js": "^7.20.3", | |||
| "videojs-flash": "^2.2.1", | |||
| "vue": "^2.6.11", | |||
| "vue-grid-layout": "^2.3.7", | |||
| "vue-lazyload": "^1.3.3", | |||
| "vue-navigation": "^1.1.4", | |||
| "vue-router": "^3.1.6" | |||
| }, | |||
| "devDependencies": { | |||
| "@amap/amap-jsapi-loader": "0.0.1", | |||
| "@vue/cli-plugin-babel": "~4.3.0", | |||
| "@vue/cli-plugin-eslint": "~4.3.0", | |||
| "@vue/cli-plugin-router": "~4.3.0", | |||
| "@vue/cli-plugin-vuex": "~4.3.0", | |||
| "@vue/cli-service": "~4.3.0", | |||
| "@vue/eslint-config-prettier": "^6.0.0", | |||
| "babel-eslint": "^10.1.0", | |||
| "babel-plugin-component": "^1.1.1", | |||
| "babel-plugin-lodash": "^3.3.4", | |||
| "compression-webpack-plugin": "^3.1.0", | |||
| "copy-webpack-plugin": "^6.0.2", | |||
| "cross-env": "^7.0.2", | |||
| "eslint": "^6.7.2", | |||
| "eslint-plugin-prettier": "^3.1.1", | |||
| "eslint-plugin-vue": "^6.2.2", | |||
| "imagemin-mozjpeg": "^8.0.0", | |||
| "imagemin-webp-webpack-plugin": "^3.3.1", | |||
| "imagemin-webpack-plugin": "^2.4.2", | |||
| "jquery": "^3.6.1", | |||
| "prettier": "^1.19.1", | |||
| "sass": "^1.26.3", | |||
| "sass-loader": "^8.0.2", | |||
| "vue-awesome-swiper": "^3.1.3", | |||
| "vue-template-compiler": "^2.6.11", | |||
| "webpack-bundle-analyzer": "^3.7.0" | |||
| } | |||
| } | |||
| @@ -0,0 +1,515 @@ | |||
| { | |||
| "ttsControlEnable": true, | |||
| "qp": { | |||
| "type": 1, | |||
| "equip_no": "2", | |||
| "set_no": "2", | |||
| "value": "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| "name": "全屏", | |||
| "info": "已为您打开全屏", | |||
| "top": 0 | |||
| }, | |||
| "fhsy": { | |||
| "type": 1, | |||
| "equip_no": "2", | |||
| "set_no": "1701", | |||
| "value": "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| "name": "首页", | |||
| "info": "已返回首页", | |||
| "top": 0 | |||
| }, | |||
| "af_open": { | |||
| "type": 3, | |||
| "path": "/api/real/Security/setup_SecurityOpenPage", | |||
| "data": { | |||
| "page_no": "2", | |||
| "mes": "打开安防态势" | |||
| }, | |||
| "msg": "已为您打开安防态势" | |||
| }, | |||
| "af_camera_open":{ | |||
| "type": 3, | |||
| "path": "/api/real/Security/setup_CameraService", | |||
| "data": { | |||
| "page_no": "2", | |||
| "mes": "园区监控", | |||
| "equip_no":2, | |||
| "value":1, | |||
| "set_no": "" | |||
| }, | |||
| "msg": "已为您打开园区监控" | |||
| }, | |||
| "ny_open": { | |||
| "type": 3, | |||
| "path": "/api/real/Comprehensive/setup_EnergyOpenPage", | |||
| "data": { | |||
| "page_no": "5", | |||
| "mes": "打开能源态势" | |||
| }, | |||
| "msg": "已为您打开能源态势" | |||
| }, | |||
| "xf_open": { | |||
| "type": 3, | |||
| "path": "/api/real/Comprehensive/setup_FireControlOpenPage", | |||
| "data": { | |||
| "page_no": "6", | |||
| "mes": "打开消防态势" | |||
| }, | |||
| "msg": "已为您打开消防态势" | |||
| }, | |||
| "zhh_open": { | |||
| "type": 3, | |||
| "path": "/api/real/Comprehensive/setup_ComprehensiveOpenPage", | |||
| "data": { | |||
| "page_no": "1", | |||
| "mes": "打开综合态势" | |||
| }, | |||
| "msg": "已为您打开综合态势" | |||
| }, | |||
| "zhh_company_open": { | |||
| "type": 3, | |||
| "path": "/api/real/Comprehensive/setup_CompanyInfo", | |||
| "data": { | |||
| "page_no": 1, | |||
| "mes": "打开公司介绍", | |||
| "companyFlag":1, | |||
| "companyName":"" | |||
| }, | |||
| "msg": "#[companyInfo]" | |||
| }, | |||
| "ry_open": { | |||
| "type": 3, | |||
| "mes": "打开人员态势", | |||
| "path": "/api/real/Person/post_PersonOpenPage", | |||
| "data": { | |||
| "page_no": "3", | |||
| "mes": "打开人员态势" | |||
| }, | |||
| "msg": "", | |||
| "after_exec": "ry_sj" | |||
| }, | |||
| "qqbj_open": { | |||
| "type": 3, | |||
| "path": "/api/real/Comprehensive/setup_GlobalOpenPage", | |||
| "data": { | |||
| "page_no": "7", | |||
| "page_action":"1", | |||
| "mes": "打开全球业务布局" | |||
| }, | |||
| "msg": "已为您打开全球业务布局" | |||
| }, | |||
| "cnbj_open": { | |||
| "type": 3, | |||
| "path": "/api/real/Comprehensive/setup_ChinaOpenPage", | |||
| "data": { | |||
| "page_no": "8", | |||
| "page_action":"1", | |||
| "mes": "打开中国业务布局" | |||
| }, | |||
| "msg": "已为您打开中国业务布局" | |||
| }, | |||
| "ab_open": { | |||
| "type": 3, | |||
| "mes": "打开奥北科技园", | |||
| "path": "/api/real/Comprehensive/setup_ScienceParkOpenPage", | |||
| "data": { | |||
| "page_no": "9", | |||
| "page_action": "1", | |||
| "mes": "打开奥北科技园" | |||
| }, | |||
| "msg": "已为您打开奥北科技园" | |||
| }, | |||
| "ry_sj": { | |||
| "type": 3, | |||
| "path": "/api/real/Person/post_PeopleValue", | |||
| "data": { | |||
| "page_no": "3", | |||
| "mes": "人员所有信息" | |||
| }, | |||
| "msg": "现在为您展示的是人员态势,当前20楼内总人数#[peopleCount]人,通过首层大堂闸机通行人数#[passCount]人,其中人脸识别#[faceCount]人,刷卡识别#[cardCount]人。" | |||
| }, | |||
| "ry_sb": { | |||
| "type": 3, | |||
| "path": "/api/real/Person/post_EquipCount", | |||
| "data": { | |||
| "page_no": "3", | |||
| "mes": "设备状态统计" | |||
| }, | |||
| "msg": "当前设备在线#[onLineEquip]台,设备离线#[offLineEquip]台;在线率#[onLineROL]" | |||
| }, | |||
| "ry_zlry": { | |||
| "type": 3, | |||
| "mes": "今日在楼人员统计", | |||
| "path": "/api/real/Person/post_PeopleCount", | |||
| "data": { | |||
| "page_no": "3", | |||
| "mes": "今日在楼人员统计" | |||
| }, | |||
| "msg": "当前20楼内总人数#[peopleCount]人" | |||
| }, | |||
| "ry_sbzt": { | |||
| "type": 3, | |||
| "mes": "设备状态统计", | |||
| "path": "/api/real/Person/post_EquipCount", | |||
| "data": { | |||
| "page_no": "3", | |||
| "mes": "设备状态统计" | |||
| }, | |||
| "msg": "" | |||
| }, | |||
| "ry_rycr": { | |||
| "type": 3, | |||
| "mes": "人员出入统计", | |||
| "path": "/api/real/Person/post_PeopleCountStatistics", | |||
| "data": { | |||
| "page_no": "3", | |||
| "mes": "人员出入统计" | |||
| }, | |||
| "msg": "当前20楼内通过首层大堂闸机通行进入#[enterPeopleCount]人,离开#[leavPeopleCount]人。" | |||
| }, | |||
| "ry_dkzj": { | |||
| "type": 3, | |||
| "mes": "打开闸机", | |||
| "path": "/api/real/Person/post_PersonPassRecord", | |||
| "data": { | |||
| "page_no": "3", | |||
| "equip_no": "2", | |||
| "set_no": "", | |||
| "value": "1", | |||
| "mes": "打开闸机" | |||
| }, | |||
| "setNoMapping": { | |||
| "一号通道": 674, | |||
| "二号通道": 673, | |||
| "三号通道": 672, | |||
| "四号通道": 671, | |||
| "五号通道": 670, | |||
| "一号闸机": 674, | |||
| "二号闸机": 673, | |||
| "三号闸机": 672, | |||
| "四号闸机": 671, | |||
| "五号闸机": 670 | |||
| }, | |||
| "msg": "已为您打开闸机" | |||
| }, | |||
| "tc_open": { | |||
| "type": 3, | |||
| "mes": "打开停车态势", | |||
| "path": "/api/real/Person/post_PersonOpenPage", | |||
| "data": { | |||
| "page_no": "4", | |||
| "mes": "打开停车态势" | |||
| }, | |||
| "msg": "", | |||
| "after_exec": "tc_sj" | |||
| }, | |||
| "tc_zccl": { | |||
| "type": 3, | |||
| "mes": "注册车辆统计", | |||
| "path": "/api/real/Park/post_RegisterCarCount", | |||
| "data": { | |||
| "page_no": "4", | |||
| "mes": "注册车辆统计" | |||
| }, | |||
| "msg": "园区目前注册车辆数是#[registerCarCount]辆" | |||
| }, | |||
| "tc_sj": { | |||
| "type": 3, | |||
| "mes": "停车所有信息", | |||
| "path": "/api/real/Park/post_CarValue", | |||
| "data": { | |||
| "page_no": "4", | |||
| "mes": "停车所有信息" | |||
| }, | |||
| "msg": "现在为您展示的是停车态势,当前园区总车位数量是#[allParkCount],剩余车位数量是#[leveParkCount];注册车辆数是#[registerCarCount]辆;本日车辆进入数是#[enterCarCount],离开车辆数是#[leavCarCount]。" | |||
| }, | |||
| "tc_dqcw": { | |||
| "type": 3, | |||
| "mes": "当前车位统计", | |||
| "path": "/api/real/Park/post_ParkCount", | |||
| "data": { | |||
| "page_no": "4", | |||
| "mes": "当前车位统计" | |||
| }, | |||
| "msg": "园区目前总车位数量是#[allParkCount],剩余车位数量是#[leveParkCount]" | |||
| }, | |||
| "tc_crtj": { | |||
| "type": 3, | |||
| "mes": "车辆出入统计", | |||
| "path": "/api/real/Park/post_CarCount", | |||
| "data": { | |||
| "page_no": "4", | |||
| "mes": "车辆出入统计" | |||
| }, | |||
| "msg": "园区当日车辆进入数是#[enterCarCount],离开车辆数是#[leavCarCount]" | |||
| }, | |||
| "tc_jk": { | |||
| "type": 3, | |||
| "path": "/api/real/Park/post_OpenPark", | |||
| "data": { | |||
| "page_no": "4", | |||
| "page_action":"1", | |||
| "mes": "" | |||
| }, | |||
| "msg": "好的" | |||
| }, | |||
| "tc_sbzt": { | |||
| "type": 3, | |||
| "mes": "设备状态统计", | |||
| "path": "/api/real/Park/post_EquipCount", | |||
| "data": { | |||
| "page_no": "4", | |||
| "mes": "设备状态统计" | |||
| }, | |||
| "msg": "" | |||
| }, | |||
| "company_close": { | |||
| "type": 3, | |||
| "path": "api/real/Comprehensive/setup_CompanyInfo", | |||
| "data": { | |||
| "page_no": "4", | |||
| "mes": "打开/关闭公司介绍", | |||
| "companyFlag":0, | |||
| "companyName":"" | |||
| }, | |||
| "msg": "关闭成功" | |||
| }, | |||
| "companys": [ | |||
| "翰博尔", | |||
| "华瑞", | |||
| "山石网科", | |||
| "索为", | |||
| "中创腾瑞", | |||
| "卓建国际", | |||
| "道有道", | |||
| "毫末", | |||
| "先河环保", | |||
| "恒泰证券", | |||
| "来酷", | |||
| "数据堂", | |||
| "随锐", | |||
| "臻和" | |||
| ], | |||
| "companys_match": { | |||
| "翰博尔":0, | |||
| "翰博":0, | |||
| "汉博尔":0, | |||
| "汉伯尔":0, | |||
| "华瑞": 1, | |||
| "华瑞网研": 1, | |||
| "山石网科": 2, | |||
| "索为": 3, | |||
| "所谓": 3, | |||
| "中创腾瑞": 4, | |||
| "卓建国际": 5, | |||
| "着建国际": 5, | |||
| "道有道": 6, | |||
| "道友到": 6, | |||
| "毫末": 7, | |||
| "好没": 7, | |||
| "先河环保": 8, | |||
| "恒泰证券": 9, | |||
| "来酷": 10, | |||
| "数据堂": 11, | |||
| "随锐科技": 12, | |||
| "随锐": 12, | |||
| "谁瑞": 12, | |||
| "水位": 12, | |||
| "谁为": 12, | |||
| "真和": 13, | |||
| "真核": 13 | |||
| }, | |||
| "companys_q": [ | |||
| "翰博尔", | |||
| "翰博", | |||
| "汉博尔", | |||
| "汉伯尔", | |||
| "华瑞", | |||
| "华瑞网研", | |||
| "山石网科", | |||
| "索为", | |||
| "所谓", | |||
| "中创腾瑞", | |||
| "卓建国际", | |||
| "着建国际", | |||
| "道有道", | |||
| "道友到", | |||
| "毫末", | |||
| "好没", | |||
| "先河环保", | |||
| "恒泰证券", | |||
| "来酷", | |||
| "数据堂", | |||
| "随锐科技", | |||
| "随锐", | |||
| "谁瑞", | |||
| "水瑞", | |||
| "水位", | |||
| "谁为", | |||
| "真和", | |||
| "真核" | |||
| ], | |||
| "doors": [ | |||
| "一号通道", | |||
| "二号通道", | |||
| "三号通道", | |||
| "四号通道", | |||
| "五号通道", | |||
| "一号闸机", | |||
| "二号闸机", | |||
| "三号闸机", | |||
| "四号闸机", | |||
| "五号闸机" | |||
| ], | |||
| "parks": [ | |||
| "地上出入口", | |||
| "B1停车场", | |||
| "B2停车场" | |||
| ], | |||
| "parksMapping": { | |||
| "地上出入口": 0, | |||
| "地上停车场": 0, | |||
| "B1停车场": 1, | |||
| "be停车场": 1, | |||
| "b1停车场": 1, | |||
| "负1停车场": 1, | |||
| "负一停车场": 1, | |||
| "附一停车场": 1, | |||
| "B2停车场": 2, | |||
| "b2停车场": 2, | |||
| "br停车场": 2 | |||
| }, | |||
| "hbh": { | |||
| "type": 2, | |||
| "forward_answer": [ | |||
| "好", | |||
| "好的", | |||
| "行", | |||
| "可以", | |||
| "好吧" | |||
| ], | |||
| "positive_answer": [ | |||
| "不好", | |||
| "不可以", | |||
| "不行" | |||
| ], | |||
| "forward_text": "京信局的展台设计以北斗七星为灵感,展台分为三大区域,城市数据建设展示区、应用场景展示区、北京数字经济展示区。请问您想了解哪个区域呢?", | |||
| "positive_text": "好吧,您先自己随便逛逛,有需要再叫我" | |||
| }, | |||
| "shoudaoduanxi": { | |||
| "type": 2, | |||
| "forward_answer": [ | |||
| "是", | |||
| "是的", | |||
| "收到", | |||
| "已收到", | |||
| "收到了" | |||
| ], | |||
| "positive_answer": [ | |||
| "否", | |||
| "没", | |||
| "没收到", | |||
| "我没收到", | |||
| "还没收到", | |||
| "没有", | |||
| "没有收到", | |||
| "未收到" | |||
| ], | |||
| "forward_text": "您收到短信的手机号后四位是多少?", | |||
| "positive_text": "额,抱歉,请您自行联系将要拜访的人员。", | |||
| "req": "duanxin" | |||
| }, | |||
| "duanxin": { | |||
| "type": 2, | |||
| "forward_text": "已匹配到您的拜访记录,将为您打开闸机,请通行!", | |||
| "forward_motion": "showRightHandBottom", | |||
| "positive_text": "抱歉,未匹配到您的邀约记录,请您联系将要拜访的人员。", | |||
| "positive_motion": "bow", | |||
| "callback": 1 | |||
| }, | |||
| "clothes": { | |||
| "SweetGirl": [ | |||
| "suit_blue", | |||
| "suit_red", | |||
| "waistcoat_blue" | |||
| ], | |||
| "BusinessGirl": [ | |||
| "suit_green", | |||
| "waistcoat_black" | |||
| ] | |||
| }, | |||
| "characters": [ | |||
| "SweetGirl", | |||
| "BusinessGirl" | |||
| ], | |||
| "zhaohu": [ | |||
| "你好", | |||
| "您好", | |||
| "小酷", | |||
| "小酷小酷", | |||
| "你好小酷", | |||
| "hello" | |||
| ], | |||
| "breakReqs": [ | |||
| "停", | |||
| "闭嘴", | |||
| "住嘴", | |||
| "stop", | |||
| "shut up" | |||
| ], | |||
| "helpReqs": [ | |||
| "我找", | |||
| "我来", | |||
| "在嘛", | |||
| "这里是", | |||
| "来找", | |||
| "送快递", | |||
| "送外卖", | |||
| "卢总", | |||
| "王总" | |||
| ], | |||
| "asks": { | |||
| "mgr": "", | |||
| "emp": "您已打卡成功", | |||
| "emp2": "", | |||
| "keyVisitor": "欢迎来到来酷智联,卢总已在办公室等您。", | |||
| "keyVisitor2": "", | |||
| "visitor": "好久不见,您先在会议室稍坐会,已通知到我的同事", | |||
| "visitor2": "", | |||
| "courier": "根据大厦防疫规定,快递外卖人员不可进入大厦,请您在大厦外联系相关人员。", | |||
| "blackRole": "你是黑名单人员,不允许进入本公司,请赶快离开!", | |||
| "default": "请问您是员工还是访客?" | |||
| }, | |||
| "normal": [ | |||
| "很高兴为您服务", | |||
| "您今天状态真好", | |||
| "您今天心情挺好的吧", | |||
| "问问我喜欢什么吧", | |||
| "近来挺顺利的吧", | |||
| "天渐凉,早晚记得多穿点" | |||
| ], | |||
| "handleTtsTexts": [ | |||
| "jdyl", | |||
| "zdyl", | |||
| "cqqd", | |||
| "xxym", | |||
| "tsym", | |||
| "sjym", | |||
| "szym" | |||
| ] | |||
| } | |||
| @@ -0,0 +1,85 @@ | |||
| const Glod = { | |||
| qp: { | |||
| type: 1, | |||
| equip_no: "2", | |||
| set_no: "2", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开全屏" | |||
| }, | |||
| fhsy: { | |||
| type: 1, | |||
| equip_no: "2", | |||
| set_no: "1701", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "返回首页" | |||
| }, | |||
| zhts: { | |||
| type: 1, | |||
| equip_no: "2", | |||
| set_no: "103", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开综合态势" | |||
| }, | |||
| afts: { | |||
| type: 1, | |||
| equip_no: "2", | |||
| set_no: "104", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开安防态势" | |||
| }, | |||
| ryts: { | |||
| type: 1, | |||
| equip_no: "2", | |||
| set_no: "105", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开人员态势" | |||
| }, | |||
| tcts: { | |||
| type: 1, | |||
| equip_no: "2", | |||
| set_no: "106", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开停车态势" | |||
| }, | |||
| nyts: { | |||
| type: 1, | |||
| equip_no: "2", | |||
| set_no: "107", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开能源态势" | |||
| }, | |||
| xfts: { | |||
| type: 1, | |||
| equip_no: "2", | |||
| set_no: "108", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开消防态势" | |||
| }, | |||
| xmdsxt: { | |||
| type: 1, | |||
| equip_no: "1005", | |||
| set_no: "2", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开西门东侧摄像头" | |||
| }, | |||
| hys1bsxt: { | |||
| type: 1, | |||
| equip_no: "1005", | |||
| set_no: "3", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开一号会议室北侧摄像头" | |||
| }, | |||
| dtmxsxt: { | |||
| type: 1, | |||
| equip_no: "1005", | |||
| set_no: "4", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开大堂门口西侧摄像头" | |||
| }, | |||
| hbh: { | |||
| type: 2, | |||
| forward_text: | |||
| "京信局的展台设计以北斗七星为灵感,展台分为三大区域,城市数据建设展示区、应用场景展示区、北京数字经济展示区。", | |||
| positive_text: "好吧,您请自便" | |||
| } | |||
| }; | |||
| @@ -0,0 +1,20 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="utf-8"> | |||
| <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | |||
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||
| <meta http-equiv="x-dns-prefetch-control" content="on" /> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |||
| <link rel="icon" href="<%= BASE_URL %>favicon.ico"> | |||
| <title><%= htmlWebpackPlugin.options.title %></title> | |||
| </head> | |||
| <body> | |||
| <noscript> | |||
| <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> | |||
| </noscript> | |||
| <div id="app"></div> | |||
| <!-- built files will be auto injected --> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,106 @@ | |||
| <template> | |||
| <div id="app" class="no-scrollbar" style="width: 100%;"> | |||
| <navigation> | |||
| <router-view :style="content"></router-view> | |||
| </navigation> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: "App", | |||
| data() { | |||
| return { | |||
| isRouterAlive: true, | |||
| chatData: [], | |||
| weatherData: null, | |||
| interactive: "", | |||
| content: "", | |||
| retryLoadClientType: 0 | |||
| }; | |||
| }, | |||
| mounted() { | |||
| window._ = _; | |||
| Date.prototype.Format = function(fmt) { | |||
| var o = { | |||
| "M+": this.getMonth() + 1, // 月份 | |||
| "d+": this.getDate(), // 日 | |||
| "h+": this.getHours(), // 小时 | |||
| "m+": this.getMinutes(), // 分 | |||
| "s+": this.getSeconds(), // 秒 | |||
| "q+": Math.floor((this.getMonth() + 3) / 3), // 季度 | |||
| S: this.getMilliseconds() // 毫秒 | |||
| }; | |||
| if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); | |||
| for (var k in o) | |||
| if (new RegExp("(" + k + ")").test(fmt)) | |||
| fmt = fmt.replace( | |||
| RegExp.$1, | |||
| RegExp.$1.length === 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length) | |||
| ); | |||
| return fmt; | |||
| }; | |||
| } | |||
| }; | |||
| </script> | |||
| <style lang="scss"> | |||
| * { | |||
| margin: 0; | |||
| padding: 0; | |||
| } | |||
| html, | |||
| body { | |||
| width: 100%; | |||
| height: 100%; | |||
| overflow-x: hidden; | |||
| overflow-y: hidden; | |||
| } | |||
| #app { | |||
| width: 100%; | |||
| height: 100%; | |||
| font-family: Avenir, Helvetica, Arial, sans-serif; | |||
| -webkit-font-smoothing: antialiased; | |||
| -moz-osx-font-smoothing: grayscale; | |||
| text-align: center; | |||
| color: #2c3e50; | |||
| } | |||
| // 隐藏滚轮 | |||
| .no-scrollbar { | |||
| -ms-overflow-style: none; | |||
| overflow: -moz-scrollbars-none; | |||
| /*background-color: black;*/ | |||
| -webkit-touch-callout: none; | |||
| -webkit-user-select: none; | |||
| -khtml-user-select: none; | |||
| -moz-user-select: none; | |||
| -ms-user-select: none; | |||
| user-select: none; | |||
| } | |||
| .no-scrollbar::-webkit-scrollbar { | |||
| width: 0 !important; | |||
| } | |||
| img { | |||
| width: auto; | |||
| height: auto; | |||
| max-width: 100%; | |||
| max-height: 100%; | |||
| } | |||
| img[lazy="loading"] { | |||
| background-color: white; | |||
| } | |||
| .single-line-text { | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| white-space: nowrap; | |||
| display: block !important; | |||
| text-align: left; | |||
| -webkit-line-clamp: 1; | |||
| -webkit-box-orient: vertical; | |||
| } | |||
| </style> | |||
| @@ -0,0 +1,451 @@ | |||
| export default { | |||
| /** | |||
| * 初始化SDK 传入onReceiveCmd, 用于接收nlp, a, reload等命令 | |||
| * @param onReceiveCmd | |||
| * @param config | |||
| */ | |||
| init( | |||
| onReceiveCmd, | |||
| config = { | |||
| jsHandleTts: false, | |||
| jsHandleState: false | |||
| } | |||
| ) { | |||
| window.sendCmd = function(cmd, params) { | |||
| if (cmd === "onBind") { | |||
| ue.cloudminds.hue("onstart", JSON.stringify(config)); | |||
| console.info("onStart event sent"); | |||
| window.cloudiaConfig = params; | |||
| if (params && params.SweetGirlClothes) { | |||
| cloudiaConfig.girls = new Map(); | |||
| cloudiaConfig.sweetGirlClothes = params.SweetGirlClothes.replace(" ", "").split(","); | |||
| cloudiaConfig.girls.set("SweetGirl", cloudiaConfig.sweetGirlClothes); | |||
| cloudiaConfig.allClothes = cloudiaConfig.girls.get("SweetGirl"); | |||
| if (params.BusinessGirlClothes) { | |||
| cloudiaConfig.businessGirlClothes = params.BusinessGirlClothes.replace(" ", "").split(","); | |||
| cloudiaConfig.girls.set("BusinessGirl", cloudiaConfig.businessGirlClothes); | |||
| } | |||
| if (params.AncientGirlClothes) { | |||
| cloudiaConfig.ancientGirlClothes = params.AncientGirlClothes.replace(" ", "").split(","); | |||
| cloudiaConfig.girls.set("AncientGirl", cloudiaConfig.ancientGirlClothes); | |||
| } | |||
| } | |||
| } | |||
| return onReceiveCmd(cmd, params); | |||
| }; | |||
| }, | |||
| reloadClothes() { | |||
| if (cloudiaConfig && cloudiaConfig.SweetGirlClothes) { | |||
| cloudiaConfig.allClothes = cloudiaConfig.girls.get(cloudiaConfig.currentCharacter); | |||
| } | |||
| }, | |||
| isNotValidNum(value) { | |||
| return !/(^[\-0-9][0-9]*(.[0-9]+)?)$/.test(value); | |||
| }, | |||
| isEmpty(obj) { | |||
| return typeof obj === "undefined" || obj == null || obj === ""; | |||
| }, | |||
| /** | |||
| * 显示toast | |||
| * @param msg toast内容 | |||
| */ | |||
| showToast(msg) { | |||
| if (ue.cloudminds) { | |||
| if (this.isEmpty(msg)) { | |||
| console.warn("Invalid call:showToast"); | |||
| return false; | |||
| } | |||
| ue.cloudminds.hue("showtoast", msg); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * 显示长toast | |||
| * @param msg toast内容 | |||
| */ | |||
| showLongToast(msg) { | |||
| if (ue.cloudminds) { | |||
| if (this.isEmpty(msg)) { | |||
| console.warn("Invalid call:showLongToast"); | |||
| return false; | |||
| } | |||
| ue.cloudminds.hue("showlongtoast", msg); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * 语音播报 | |||
| * @param text 播报的内容 | |||
| */ | |||
| playTts(text) { | |||
| if (ue.cloudminds) { | |||
| if (this.isEmpty(text)) { | |||
| console.warn("Invalid call:playTts"); | |||
| return false; | |||
| } | |||
| ue.cloudminds.hue("playtts", text); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * 修改浏览器位置 | |||
| * @param left 浏览器距离屏幕左边的位置 | |||
| * @param top 浏览器距离屏幕上边的位置 | |||
| * @param right 浏览器距离屏幕右边的位置 | |||
| * @param bottom 浏览器距离屏幕下边的位置 | |||
| */ | |||
| updateBrowserLocation(left, top, right, bottom) { | |||
| if ( | |||
| this.isNotValidNum(left) || | |||
| this.isNotValidNum(top) || | |||
| this.isNotValidNum(right) || | |||
| this.isNotValidNum(bottom) | |||
| ) { | |||
| console.error("updateBrowserLocation 数据不合法"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| // 蓝图端用的是","分隔方案 | |||
| ue.cloudminds.hue("updatebrowserlocation", left + ", " + top + ", " + right + ", " + bottom); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * 修改虚拟人物位置 | |||
| * @param locationX X坐标值 | |||
| * @param locationY Y坐标值 | |||
| * @param locationZ Z坐标值 | |||
| * @param persistence 是否持久化保存 | |||
| */ | |||
| updateCharacterLocation(locationX, locationY, locationZ, persistence = false) { | |||
| if (this.isNotValidNum(locationX) || this.isNotValidNum(locationY) || this.isNotValidNum(locationZ)) { | |||
| console.error("updateCharacterLocation 数据不合法"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue( | |||
| "updatecharacterlocation", | |||
| locationX + "#$*&@" + locationY + "#$*&@" + locationZ + "#$*&@" + persistence | |||
| ); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * 修改虚拟人物旋转角度 | |||
| * @param rotationP P坐标值 | |||
| * @param rotationY Y坐标值 | |||
| * @param rotationR R坐标值 | |||
| * @param persistence 是否持久化保存 | |||
| */ | |||
| updateCharacterRotation(rotationP, rotationY, rotationR, persistence = false) { | |||
| if (this.isNotValidNum(rotationP) || this.isNotValidNum(rotationY) || this.isNotValidNum(rotationR)) { | |||
| console.error("updateCharacterRotation 数据不合法"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue( | |||
| "updatecharacterrotation", | |||
| rotationP + "#$*&@" + rotationY + "#$*&@" + rotationR + "#$*&@" + persistence | |||
| ); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * 播放动画 | |||
| * @param name 动画名称 | |||
| * @param status 动画状态 | |||
| */ | |||
| playMotion(name, status = "") { | |||
| if (ue.cloudminds) { | |||
| if (this.isEmpty(name)) { | |||
| console.warn("Invalid call:playMotion"); | |||
| return false; | |||
| } | |||
| if (status.length === 0) { | |||
| ue.cloudminds.hue("playmotion", name); | |||
| } else { | |||
| ue.cloudminds.hue("playmotion", name + "#$*&@" + status); | |||
| } | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * 设置表情 | |||
| * @param exp 表情名称 | |||
| * @param value 值 | |||
| */ | |||
| setExpression(exp, value) { | |||
| if (ue.cloudminds) { | |||
| if (this.isEmpty(value) || this.isEmpty(exp)) { | |||
| console.warn("Invalid call:setExpression"); | |||
| return false; | |||
| } | |||
| ue.cloudminds.hue("setexpression", exp + "#$*&@" + value); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * @param color 背景墙颜色 | |||
| */ | |||
| setBgWallColor(color) { | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setMapBgColor", color); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * @param wall 背景墙资源名称 | |||
| */ | |||
| setBgWallResource(wall) { | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setMapBgResource", wall); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * 设置是否由js接管tts播报,接管之后,app将不负责播报,转而由js负责调用palytts进行播报 | |||
| * @param enable | |||
| */ | |||
| setJsPlayTtsEnabled(enable) { | |||
| if (this.isEmpty(enable)) { | |||
| console.warn("Invalid call:setJsPlayTtsEnabled"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setjsplayttsenabled", enable.toString()); | |||
| } | |||
| return true; | |||
| }, | |||
| /** | |||
| * 设置是否由js接管state,接管之后,app将不切换state | |||
| * @param enable | |||
| */ | |||
| setJsHandleStateEnabled(enable) { | |||
| if (this.isEmpty(enable)) { | |||
| console.warn("Invalid call:setJsHandleStateEnabled"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setJsHandleStateEnabled", enable.toString()); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| /** | |||
| * 获取deviceId,调用成功之后会在onCmdReceived中收到deviceId的命令 | |||
| * @deprecated 请改用getRobotInfoConfig("RobotId")方法 | |||
| */ | |||
| getDeviceId() { | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("getdeviceid"); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| getRobotInfoConfig(key) { | |||
| if (ue.cloudminds) { | |||
| if (this.isEmpty(key)) { | |||
| console.warn("Invalid call:getRobotInfoConfig"); | |||
| return false; | |||
| } | |||
| return ue.cloudminds.hueget("getrobotinfoconfig", key); | |||
| } | |||
| return new Promise(function() { | |||
| return ""; | |||
| }); | |||
| }, | |||
| getGreetingMsg() { | |||
| return this.getAppConfig(); | |||
| }, | |||
| getAppConfig() { | |||
| if (ue.cloudminds) { | |||
| return ue.cloudminds.hueget("getappconfig"); | |||
| } | |||
| return new Promise(function() { | |||
| return ""; | |||
| }); | |||
| }, | |||
| getCharacter() { | |||
| if (ue.cloudminds) { | |||
| return ue.cloudminds.hueget("getcharacterinfo"); | |||
| } | |||
| return new Promise(function() { | |||
| return ""; | |||
| }); | |||
| }, | |||
| setCharacter(cname) { | |||
| if (this.isEmpty(cname)) { | |||
| console.warn("Invalid call:setCharacter"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setcharacter", cname); | |||
| if (cloudiaConfig) { | |||
| cloudiaConfig.currentCharacter = cname; | |||
| } | |||
| this.reloadClothes(); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| setClothes(name) { | |||
| if (cloudiaConfig && cloudiaConfig.allClothes && !cloudiaConfig.allClothes.indexOf(name) < 0) { | |||
| console.warn("Invalid call:setClothes:" + name); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setClothes", name); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| postMediaEvent(event) { | |||
| if (this.isEmpty(event)) { | |||
| console.warn("Invalid call:postMediaEvent"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("postmediaevent", event); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| setAsrWakeUpEnable(enable) { | |||
| if (this.isEmpty(enable)) { | |||
| console.warn("Invalid call:setAsrWakeUpEnable"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setAsrWakeUpEnable", enable.toString()); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| stopPlayTts(playOK = false) { | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("stopTts", playOK.toString()); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| setWalkGreetingEnable(enable) { | |||
| if (this.isEmpty(enable)) { | |||
| console.warn("Invalid call:setWalkGreetEnable"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("walkGreetEnable", enable.toString()); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| setWallLocation(location) { | |||
| if (this.isEmpty(location)) { | |||
| console.warn("Invalid call:setWallLocation"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setbgwalllocation", location); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| enterImmerseMode(immerse) { | |||
| if (this.isEmpty(immerse)) { | |||
| console.warn("Invalid call:enterImmerseMode"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("enterImmerseMode", immerse.toString()); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| startVideoTalk() { | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("starttalk"); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| stopVideoTalk() { | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("endtalk"); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| textTriggerNlp(text) { | |||
| if (this.isEmpty(text)) { | |||
| console.warn("Invalid call:textTriggerNlp"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("texttriggernlp", text); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| setVolume(vol) { | |||
| if (this.isNotValidNum(vol)) { | |||
| console.warn("Invalid call:setVolume:" + vol); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setvolume", vol.toString()); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| getVolume() { | |||
| if (ue.cloudminds) { | |||
| return ue.cloudminds.hueget("getcurvolume"); | |||
| } | |||
| return new Promise(function() { | |||
| return "11"; | |||
| }); | |||
| }, | |||
| downloadFiles(tag, urls) { | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("downloadfiles", tag + "#$*&@" + urls); | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| updateCharacterScaleLevel(scaleLevel, persistence = false) { | |||
| if (this.isNotValidNum(scaleLevel)) { | |||
| console.warn("Invalid call:setVolume:" + persistence); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setcharacterscale", scaleLevel + "#$*&@" + persistence); | |||
| return true; | |||
| } | |||
| }, | |||
| restartH5() { | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("reopenbrowser"); | |||
| } | |||
| }, | |||
| setState(state) { | |||
| if (this.isEmpty(state)) { | |||
| console.warn("Invalid call:setState"); | |||
| return false; | |||
| } | |||
| if (ue.cloudminds) { | |||
| ue.cloudminds.hue("setState", state); | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| }; | |||
| @@ -0,0 +1,684 @@ | |||
| <template> | |||
| <div :v-model="testing"> | |||
| <div class="api-layout m-button"> | |||
| <input | |||
| type="button" | |||
| value="一键自测" | |||
| class="input-text input-button" | |||
| style="margin: 0; width: 100%; text-align: center;" | |||
| @click="testAllInterface(toast)" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceShowToast'])"> | |||
| <input v-model="toast" type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="showToast" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceShowToast()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceShowLongToast'])"> | |||
| <input v-model="longToast" type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="longToast" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceShowLongToast()" | |||
| /> | |||
| </div> | |||
| <div :class="iPlayTts ? 'api-layout' : getValidClass(allInterfaces['interfacePlayTts'])"> | |||
| <input v-model="tts" type="text" class="input-text" /> | |||
| <input type="button" value="playTts" class="input-text input-button" @click="interfacePlayTts()" /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceUpdateBrowserLocation'])"> | |||
| <input v-model="bOffset" type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="browser" | |||
| class="input-text input-button" | |||
| @click="interfaceUpdateBrowserLocation()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceUpdateCharacterLocation'])"> | |||
| <input v-model="cLocation" type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="location" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceUpdateCharacterLocation()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceUpdateCharacterRotation'])"> | |||
| <input v-model="cRotation" type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="rotation" | |||
| class="input-text input-button" | |||
| @click="interfaceUpdateCharacterRotation()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceUpdateWallLocation'])"> | |||
| <input v-model="bgLocation" type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="WallLocation" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceUpdateWallLocation()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfacePlayMotion'])"> | |||
| <label class="input-text select_wrapper"> | |||
| <select v-model="motion" class="input-text selection"> | |||
| <option>idle</option> | |||
| <option>nod</option> | |||
| <option>shakeHead</option> | |||
| <option>bow</option> | |||
| <option>handWave</option> | |||
| <option>showLeftHand</option> | |||
| <option>showLeftHandTop</option> | |||
| <option>showLeftHandBottom</option> | |||
| <option>showRightHand</option> | |||
| <option>showRightHandTop</option> | |||
| <option>showRightHandBottom</option> | |||
| <option>showBothHandBottom</option> | |||
| </select> | |||
| </label> | |||
| <input | |||
| type="button" | |||
| value="playMotion" | |||
| class="input-text input-button m-button" | |||
| @click="interfacePlayMotion()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceSetBgWallColor']) + ' input-color-layout'"> | |||
| <div class="input-text"> | |||
| <span class="input-color-text">{{ wall }}</span> | |||
| </div> | |||
| <input | |||
| id="color" | |||
| type="color" | |||
| name="color" | |||
| value="#00f4ff" | |||
| class="input-text input-color-button m-button" | |||
| @change="interfaceSetBgWallColor()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceSetBgWallRes'])"> | |||
| <label class="input-text select_wrapper"> | |||
| <select v-model="wallRes" class="input-text selection"> | |||
| <option>3DRoom</option> | |||
| <option>SolidColor</option> | |||
| <option>Landscape</option> | |||
| </select> | |||
| </label> | |||
| <input | |||
| type="button" | |||
| value="setMapRes" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceSetBgWallRes()" | |||
| /> | |||
| </div> | |||
| <div :class="iGetRobotConfig ? 'api-layout' : getValidClass(allInterfaces['interfaceGetDeviceId'])"> | |||
| <input v-model="deviceId" type="text" class="input-text" /> | |||
| <input type="button" value="DeviceId" class="input-text input-button" @click="interfaceGetDeviceId()" /> | |||
| </div> | |||
| <div :class="iAppConfig ? 'api-layout' : getValidClass(allInterfaces['interfaceGetAppConfig'])"> | |||
| <input v-model="appConfig" type="text" class="input-text" /> | |||
| <input type="button" value="AppConfig" class="input-text input-button" @click="interfaceGetAppConfig()" /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceSetCharacter'])"> | |||
| <label class="input-text select_wrapper"> | |||
| <select v-model="character" class="input-text selection"> | |||
| <option>SweetGirl</option> | |||
| <option>BusinessGirl</option> | |||
| <option>AncientGirl</option> | |||
| </select> | |||
| </label> | |||
| <input | |||
| type="button" | |||
| value="setCharacter" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceSetCharacter()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceSetClothes'])"> | |||
| <label class="input-text select_wrapper"> | |||
| <select v-model="clothes" class="input-text selection"> | |||
| <option v-for="c in allClothes" :key="c">{{ c }}</option> | |||
| </select> | |||
| </label> | |||
| <input | |||
| type="button" | |||
| value="setClothes" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceSetClothes()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfacePostMediaEvent'])"> | |||
| <label class="input-text select_wrapper"> | |||
| <select v-model="mediaEvent" class="input-text selection"> | |||
| <option>playing</option> | |||
| <option>pause</option> | |||
| <option>ended</option> | |||
| </select> | |||
| </label> | |||
| <input | |||
| type="button" | |||
| value="postMediaEvent" | |||
| class="input-text input-button m-button" | |||
| @click="interfacePostMediaEvent()" | |||
| /> | |||
| </div> | |||
| <div :class="iAsrWakeUp ? 'api-layout' : getValidClass(allInterfaces['interfaceSetAsrWakeUpEnable'])"> | |||
| <input v-model="asrWakeUp" type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="Asr Wake Up" | |||
| class="input-text input-button" | |||
| @click="interfaceSetAsrWakeUpEnable()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceStopPlayTts'])"> | |||
| <input disabled type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="StopPlayTts" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceStopPlayTts()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceEnterImmerseMode'])"> | |||
| <input v-model="immerseMode" type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="immerseMode" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceEnterImmerseMode()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceStartVideoTalk'])"> | |||
| <input | |||
| type="button" | |||
| value="StartVideoTalk" | |||
| class="input-text" | |||
| style="width: 61vw;" | |||
| @click="interfaceStartVideoTalk()" | |||
| /> | |||
| <input | |||
| type="button" | |||
| value="StopVideoTalk" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceStopVideoTalk()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceSetVolume'])"> | |||
| <input v-model="setValueText" type="text" class="input-text" /> | |||
| <input type="button" value="setVolume" class="input-text input-button" @click="interfaceSetVolume()" /> | |||
| </div> | |||
| <div :class="iGetVolume ? 'api-layout' : getValidClass(allInterfaces['interfaceGetVolume'])"> | |||
| <input v-model="getValueText" type="text" class="input-text" /> | |||
| <input type="button" value="getVolume" class="input-text input-button" @click="interfaceGetVolume()" /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceDownloadFiles'])"> | |||
| <input disabled type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="downloadFiles" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceDownloadFiles()" | |||
| /> | |||
| </div> | |||
| <div :class="getValidClass(allInterfaces['interfaceTextTriggerNlp'])"> | |||
| <input v-model="ttsText" type="text" class="input-text" /> | |||
| <input | |||
| type="button" | |||
| value="TriggerNlp" | |||
| class="input-text input-button m-button" | |||
| @click="interfaceTextTriggerNlp()" | |||
| /> | |||
| </div> | |||
| <div class="api-layout"> | |||
| <input disabled type="text" class="input-text" /> | |||
| <input type="button" value="LoadAd" class="input-text input-button" @click="loadAd()" /> | |||
| </div> | |||
| <div class="api-layout"> | |||
| <p>cloudminds</p> | |||
| </div> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| var timer; | |||
| import Cloudia from "../api/cloudia-sdk-v1.4.1"; | |||
| export default { | |||
| name: "DemoView", | |||
| components: {}, | |||
| data() { | |||
| return { | |||
| toast: "A Toast", | |||
| longToast: "A Long Toast", | |||
| tts: "1234567890", | |||
| bOffset: "0, 0, 0, 0", | |||
| cLocation: "-378.8,-0.7,448.3,false", | |||
| cRotation: "0,179.5,0,false", | |||
| motion: "bow", | |||
| wall: "Change BG Color", | |||
| wallRes: "3DRoom", | |||
| exp: "smile, 1", | |||
| mediaEvent: "playing", | |||
| asrWakeUp: true, | |||
| walkGreetEnable: true, | |||
| cameraMode: "level", | |||
| bgLocation: "1400,0,0", | |||
| setValueText: 12, | |||
| getValueText: 0, | |||
| ttsText: "成都天气", | |||
| deviceId: 0, | |||
| testing: true, | |||
| iPlayTts: true, | |||
| iAsrWakeUp: true, | |||
| iGetRobotConfig: true, | |||
| iAppConfig: true, | |||
| iGetVolume: true, | |||
| allInterfaces: new Map(), | |||
| cloudiaEvents: new Map(), | |||
| appConfig: "", | |||
| character: "SweetGirl", | |||
| allClothes: [], | |||
| clothes: "suit_blue", | |||
| immerseMode: false, | |||
| asrEnabled: true | |||
| }; | |||
| }, | |||
| computed: {}, | |||
| watch: {}, | |||
| mounted() { | |||
| let that = this; | |||
| if (that.$parent.tabIndex == 1) { | |||
| let getAllInterfaces = (obj) => | |||
| Object.getOwnPropertyNames(obj).filter((item) => { | |||
| if (typeof obj[item] === "function" && item.startsWith("interface")) { | |||
| that.allInterfaces.set(item, 0); | |||
| console.info(item); | |||
| return item; | |||
| } | |||
| }); | |||
| getAllInterfaces(this); | |||
| } | |||
| }, | |||
| methods: { | |||
| getValidClass(cond) { | |||
| if (cond === undefined || cond === 0) { | |||
| return "api-layout interface-init"; | |||
| } else if (cond === 1) { | |||
| return "api-layout interface-success"; | |||
| } else { | |||
| return "api-layout interface-fail"; | |||
| } | |||
| }, | |||
| interfaceShowToast() { | |||
| let result = Cloudia.showToast(this.toast); | |||
| this.allInterfaces["interfaceShowToast"] = result ? 1 : 2; | |||
| }, | |||
| interfaceShowLongToast() { | |||
| let result = Cloudia.showLongToast(this.longToast); | |||
| this.allInterfaces["interfaceShowLongToast"] = result ? 1 : 2; | |||
| }, | |||
| interfacePlayTts() { | |||
| let result = Cloudia.playTts(this.tts); | |||
| if (result) { | |||
| this.iPlayTts = true; | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(() => { | |||
| this.iPlayTts = false; | |||
| this.allInterfaces["interfacePlayTts"] = this.cloudiaEvents["ttsPlay"] === 10 ? 1 : 2; | |||
| }, 1500); | |||
| } else { | |||
| this.allInterfaces["interfacePlayTts"] = 2; | |||
| } | |||
| }, | |||
| interfaceUpdateBrowserLocation() { | |||
| this.bOffset = this.bOffset.replace(/ /g, ""); | |||
| let offset = this.bOffset.split(","); | |||
| let result = Cloudia.updateBrowserLocation(offset[0], offset[1], offset[2], offset[3]); | |||
| this.allInterfaces["interfaceUpdateBrowserLocation"] = result ? 1 : 2; | |||
| }, | |||
| interfaceUpdateCharacterLocation() { | |||
| this.cLocation = this.cLocation.replace(/ /g, ""); | |||
| let location = this.cLocation.split(","); | |||
| let result = Cloudia.updateCharacterLocation(location[0], location[1], location[2], location[3]); | |||
| this.allInterfaces["interfaceUpdateCharacterLocation"] = result ? 1 : 2; | |||
| }, | |||
| interfaceUpdateCharacterRotation() { | |||
| this.cRotation = this.cRotation.replace(/ /g, ""); | |||
| let rotation = this.cRotation.split(","); | |||
| let result = Cloudia.updateCharacterRotation(rotation[0], rotation[1], rotation[2], rotation[3]); | |||
| this.allInterfaces["interfaceUpdateCharacterRotation"] = result ? 1 : 2; | |||
| }, | |||
| interfaceUpdateWallLocation() { | |||
| let result = Cloudia.setWallLocation(this.bgLocation); | |||
| this.allInterfaces["interfaceUpdateWallLocation"] = result ? 1 : 2; | |||
| }, | |||
| interfacePlayMotion() { | |||
| this.motion = this.motion.replace(/ /g, ""); | |||
| let params = this.motion.split(","); | |||
| let result; | |||
| if (params.length === 2) { | |||
| result = Cloudia.playMotion(params[0], params[1]); | |||
| } else { | |||
| result = Cloudia.playMotion(params[0]); | |||
| } | |||
| this.allInterfaces["interfacePlayMotion"] = result ? 1 : 2; | |||
| }, | |||
| interfaceSetBgWallColor() { | |||
| //通过使用 getElementById() 来访问 <color> 元素 | |||
| let colorEl = document.getElementById("color"); | |||
| console.info("selected color:" + colorEl.value); | |||
| let color = colorEl.value.replace("#", ""); | |||
| let r = parseInt(color.substring(0, 2), 16) / 255; | |||
| let g = parseInt(color.substring(2, 4), 16) / 255; | |||
| let b = parseInt(color.substring(4, 6), 16) / 255; | |||
| // console.info("Selected color: rgb(" + r + ", " + g + ", " + b + ")"); | |||
| let result = Cloudia.setBgWallColor(r + ", " + g + ", " + b); | |||
| this.allInterfaces["interfaceSetBgWallColor"] = result ? 1 : 2; | |||
| }, | |||
| interfaceSetBgWallRes() { | |||
| let result = Cloudia.setBgWallResource(this.wallRes); | |||
| this.allInterfaces["interfaceSetBgWallRes"] = result ? 1 : 2; | |||
| }, | |||
| interfaceGetDeviceId() { | |||
| let that = this; | |||
| this.iGetRobotConfig = true; | |||
| return Cloudia.getRobotInfoConfig("RobotId").then(function(ReturnValue) { | |||
| if (ReturnValue !== undefined && ReturnValue.ReturnValue !== undefined) { | |||
| that.deviceId = ReturnValue.ReturnValue; | |||
| } | |||
| that.allInterfaces["interfaceGetDeviceId"] = that.deviceId.length > 0 ? 1 : 2; | |||
| that.iGetRobotConfig = false; | |||
| }); | |||
| }, | |||
| interfaceGetAppConfig() { | |||
| let that = this; | |||
| this.iAppConfig = true; | |||
| return Cloudia.getAppConfig().then(function(ReturnValue) { | |||
| if (ReturnValue !== undefined && ReturnValue.ReturnValue !== undefined) { | |||
| that.appConfig = ReturnValue.ReturnValue; | |||
| } | |||
| that.allInterfaces["interfaceGetAppConfig"] = that.appConfig.length > 0 ? 1 : 2; | |||
| that.iAppConfig = false; | |||
| }); | |||
| }, | |||
| interfaceSetCharacter() { | |||
| let result = Cloudia.setCharacter(this.character); | |||
| this.allClothes = cloudiaConfig.allClothes; | |||
| this.clothes = this.allClothes[0]; | |||
| this.allInterfaces["interfaceSetCharacter"] = result ? 1 : 2; | |||
| return result; | |||
| }, | |||
| interfaceSetClothes() { | |||
| let result = Cloudia.setClothes(this.clothes); | |||
| this.allInterfaces["interfaceSetClothes"] = result ? 1 : 2; | |||
| }, | |||
| interfacePostMediaEvent() { | |||
| let result = Cloudia.postMediaEvent(this.mediaEvent); | |||
| this.allInterfaces["interfacePostMediaEvent"] = result ? 1 : 2; | |||
| }, | |||
| interfaceSetAsrWakeUpEnable() { | |||
| let result = Cloudia.setAsrWakeUpEnable(this.asrWakeUp); | |||
| if (result) { | |||
| this.iAsrWakeUp = true; | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(() => { | |||
| if (this.cloudiaEvents["asrWakeUp"] === this.asrWakeUp ? 10 : 20) { | |||
| this.allInterfaces["interfaceSetAsrWakeUpEnable"] = 1; | |||
| } else { | |||
| this.allInterfaces["interfaceSetAsrWakeUpEnable"] = 2; | |||
| } | |||
| this.iAsrWakeUp = false; | |||
| }, 1000); | |||
| } else { | |||
| this.allInterfaces["interfaceSetAsrWakeUpEnable"] = 2; | |||
| } | |||
| }, | |||
| interfaceStopPlayTts() { | |||
| let result = Cloudia.stopPlayTts(false); | |||
| this.allInterfaces["interfaceStopPlayTts"] = result ? 1 : 2; | |||
| }, | |||
| interfaceEnterImmerseMode() { | |||
| let result = Cloudia.enterImmerseMode(this.immerseMode); | |||
| this.allInterfaces["interfaceEnterImmerseMode"] = result ? 1 : 2; | |||
| }, | |||
| interfaceStartVideoTalk() { | |||
| let result = Cloudia.startVideoTalk(); | |||
| this.allInterfaces["interfaceStartVideoTalk"] = result ? 1 : 2; | |||
| }, | |||
| interfaceStopVideoTalk() { | |||
| let result = Cloudia.stopVideoTalk(); | |||
| this.allInterfaces["interfaceStopVideoTalk"] = result ? 1 : 2; | |||
| }, | |||
| interfaceSetVolume() { | |||
| let result = Cloudia.setVolume(this.setValueText); | |||
| this.allInterfaces["interfaceSetVolume"] = result ? 1 : 2; | |||
| }, | |||
| interfaceGetVolume() { | |||
| this.iGetVolume = true; | |||
| return Cloudia.getVolume().then((ReturnValue) => { | |||
| if (ReturnValue !== undefined && ReturnValue.ReturnValue !== undefined) { | |||
| this.getValueText = ReturnValue.ReturnValue; | |||
| console.info("========:" + this.getValueText + ", " + this.setValueText); | |||
| this.allInterfaces["interfaceGetVolume"] = | |||
| this.getValueText.toString() === this.setValueText.toString() ? 1 : 2; | |||
| } else { | |||
| this.allInterfaces["interfaceGetVolume"] = 2; | |||
| } | |||
| this.iGetVolume = false; | |||
| }); | |||
| }, | |||
| interfaceDownloadFiles() { | |||
| let result = Cloudia.downloadFiles( | |||
| "test", | |||
| JSON.stringify([ | |||
| { | |||
| name: "04070c61b7d40b5a90b98640645493cb.jpeg", | |||
| url: "https://127.0.0.1" | |||
| }, | |||
| { | |||
| name: "112350h4wcwa94c9ch3oth.jpg", | |||
| url: "https://127.0.0.1" | |||
| } | |||
| ]) | |||
| ); | |||
| this.allInterfaces["interfaceDownloadFiles"] = result ? 1 : 2; | |||
| }, | |||
| interfaceTextTriggerNlp() { | |||
| let result = Cloudia.textTriggerNlp(this.ttsText); | |||
| this.allInterfaces["interfaceTextTriggerNlp"] = result ? 1 : 2; | |||
| }, | |||
| getRandomInt(min, max) { | |||
| min = Math.ceil(min); | |||
| max = Math.floor(max); | |||
| return Math.floor(Math.random() * (max - min)) + min; //不含最大值,含最小值 | |||
| }, | |||
| loadAd() { | |||
| // TODO !!!!不同的环境需要切换不同的baseUrl!!!! | |||
| let baseUrl = "https://127.0.0.1"; | |||
| let timestamp = new Date().getTime(); | |||
| // TODO 填写你自己的appId | |||
| let appId = Config.appId; | |||
| let nonceStr = this.getRandomInt(1000, 9999); | |||
| // TODO 填写你自己的appSecret | |||
| let appSecret = Config.appSecret; | |||
| let sign = md5("appId" + appId + "timestamp" + timestamp + "nonceStr" + nonceStr + appSecret); | |||
| // console.info("appId:" + appId); | |||
| // console.info("appSecret:" + appSecret); | |||
| // console.info("sign:" + sign); | |||
| const headers = { | |||
| "Content-Type": "application/json", | |||
| appId: appId, | |||
| timestamp: timestamp, | |||
| nonceStr: nonceStr, | |||
| sign: sign | |||
| }; | |||
| let url = "/crss-robot/ads/robotapi/v1/adSpace/get?pageCode=home&robotCode=" + this.deviceId; | |||
| fetch(baseUrl + url, { headers }) | |||
| .then(async (response) => { | |||
| const data = await response.json(); | |||
| if (!response.ok) { | |||
| // get error message from body or default to response statusText | |||
| const error = (data && data.message) || response.statusText; | |||
| return Promise.reject(error); | |||
| } | |||
| console.info("load ad data success:" + JSON.stringify(data)); | |||
| if (data.code === 0 && data.data && data.data.adList) { | |||
| // 拼接完整URL | |||
| data.data.adList.map((e) => { | |||
| e.url = baseUrl + e.url; | |||
| }); | |||
| let adData = JSON.stringify(data.data.adList); | |||
| // 下载广告数据,下载成功之后会在event事件中收到通知 | |||
| Cloudia.downloadFiles("home", adData); | |||
| console.info("ad data:" + adData); | |||
| } else { | |||
| console.warn("ad data is empty"); | |||
| } | |||
| }) | |||
| .catch((error) => { | |||
| console.error("load ad data error:" + error); | |||
| }); | |||
| }, | |||
| interFun() { | |||
| var ii = "qp"; | |||
| this.handleCustomize(ii); | |||
| }, | |||
| insertNlp() { | |||
| this.addMsgList(2, "测试一下,测试一下"); | |||
| if (this.nplList.length > 10) { | |||
| this.nplList.splice(10, this.nplList.length - 10); | |||
| } | |||
| this.nplList = [ | |||
| { question_id: new Date().getTime(), question_text: "test test", answer: "answer....." }, | |||
| ...this.nplList | |||
| ]; | |||
| this.$axios | |||
| .post(Config.serverDb + "/api/db/save", { | |||
| id: new Date().getTime(), | |||
| text: "test test", | |||
| answer: "answer....." | |||
| }) | |||
| .then((res) => { | |||
| console.log(res); | |||
| }); | |||
| }, | |||
| testAllInterface() { | |||
| let i = 0; | |||
| for (let [key, value] of this.allInterfaces) { | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(() => { | |||
| this.testing = true; | |||
| try { | |||
| this[key](); | |||
| } catch (e) { | |||
| this.allInterfaces[key] = 2; | |||
| console.error("interface exec failed:" + key + ", " + value + "----" + e); | |||
| } | |||
| this.testing = false; | |||
| }, ++i * 1000); | |||
| } | |||
| } | |||
| } | |||
| }; | |||
| </script> | |||
| <style> | |||
| .log { | |||
| height: 100%; | |||
| text-align: left; | |||
| overflow-y: scroll; | |||
| margin-right: 0; | |||
| padding-right: 0; | |||
| } | |||
| .cmd { | |||
| margin-left: 2vw; | |||
| color: #803300; | |||
| font-size: 4vh; | |||
| display: inline-block; | |||
| } | |||
| .api-layout { | |||
| margin-bottom: 0.5vh; | |||
| justify-content: left; | |||
| width: 100%; | |||
| text-align: left; | |||
| } | |||
| .input-text { | |||
| height: 6vh; | |||
| line-height: 6vh; | |||
| font-size: 3vh; | |||
| color: black; | |||
| text-align: left; | |||
| width: 60vw; | |||
| background-color: rgba(255, 255, 255, 0.4); | |||
| border: none; | |||
| padding-left: 1vw; | |||
| } | |||
| .select_wrapper { | |||
| padding: 0; | |||
| background-color: transparent; | |||
| } | |||
| .selection { | |||
| padding: 0; | |||
| width: 61vw; | |||
| background-color: rgba(255, 255, 255, 0.4); | |||
| } | |||
| .input-button { | |||
| width: 34vw; | |||
| margin-left: 2vw; | |||
| } | |||
| .m-button { | |||
| background-color: rgba(59, 140, 207, 0.5); | |||
| } | |||
| .input-color-layout { | |||
| display: -webkit-box; | |||
| } | |||
| .input-color-text { | |||
| font: 400 3vh Arial; | |||
| text-align: left; | |||
| display: contents; | |||
| } | |||
| .input-color-button { | |||
| padding: 0; | |||
| margin-left: 2vw; | |||
| width: 34vw; | |||
| display: flex; | |||
| } | |||
| .floats { | |||
| position: absolute; | |||
| right: 1vw; | |||
| width: 48vw; | |||
| text-align: right; | |||
| } | |||
| .interface-init { | |||
| background-color: transparent; | |||
| } | |||
| .interface-success { | |||
| background-color: #57b73b; | |||
| } | |||
| .interface-fail { | |||
| background-color: #803300; | |||
| } | |||
| </style> | |||
| @@ -0,0 +1,398 @@ | |||
| <template> | |||
| <div v-if="visible" :class="['json-view-container', theme, `deep-${currentDeep}`]"> | |||
| <div | |||
| :class="['json-view', length ? 'closeable' : '']" | |||
| :style="{ fontSize: fontSize + 'px', lineHeight: lineHeight + 'px' }" | |||
| > | |||
| <!--icon-style-square--> | |||
| <span v-if="length && iconStyle === 'square'" class="angle" @click="toggleClose"> | |||
| <svg | |||
| v-if="innerclosed" | |||
| :fill="iconColors[0]" | |||
| width="1em" | |||
| height="1em" | |||
| viewBox="0 0 1792 1792" | |||
| style="vertical-align: middle; color: rgb(42, 161, 152); height: 1em; width: 1em;" | |||
| > | |||
| <path | |||
| d="M1344 800v64q0 14-9 23t-23 9h-352v352q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23v-352h-352q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h352v-352q0-14 9-23t23-9h64q14 0 23 9t9 23v352h352q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z" | |||
| ></path> | |||
| </svg> | |||
| <svg | |||
| v-if="!innerclosed" | |||
| :fill="iconColors[1]" | |||
| width="1em" | |||
| height="1em" | |||
| viewBox="0 0 1792 1792" | |||
| style="vertical-align: middle; color: rgb(88, 110, 117); height: 1em; width: 1em;" | |||
| > | |||
| <path | |||
| d="M1344 800v64q0 14-9 23t-23 9h-832q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z" | |||
| ></path> | |||
| </svg> | |||
| </span> | |||
| <!--icon-style-circle--> | |||
| <span v-if="length && iconStyle === 'circle'" class="angle" @click="toggleClose"> | |||
| <svg | |||
| v-if="!innerclosed" | |||
| viewBox="0 0 24 24" | |||
| :fill="iconColors[0]" | |||
| preserveAspectRatio="xMidYMid meet" | |||
| style="vertical-align: middle; color: rgb(1, 160, 228); height: 1em; width: 1em;" | |||
| > | |||
| <path | |||
| d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M7,13H17V11H7" | |||
| ></path> | |||
| </svg> | |||
| <svg | |||
| v-if="innerclosed" | |||
| viewBox="0 0 24 24" | |||
| :fill="iconColors[1]" | |||
| preserveAspectRatio="xMidYMid meet" | |||
| style="vertical-align: middle; color: rgb(161, 106, 148); height: 1em; width: 1em;" | |||
| > | |||
| <path | |||
| d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M13,7H11V11H7V13H11V17H13V13H17V11H13V7Z" | |||
| ></path> | |||
| </svg> | |||
| </span> | |||
| <!--icon-style-triangle--> | |||
| <span v-if="length && iconStyle === 'triangle'" class="angle" @click="toggleClose"> | |||
| <svg | |||
| v-if="!innerclosed" | |||
| viewBox="0 0 15 15" | |||
| :fill="iconColors[0]" | |||
| style="vertical-align: top; color: #3c4047; height: 1em; width: 1em; padding-left: 2px;" | |||
| > | |||
| <path d="M0 5l6 6 6-6z"></path> | |||
| </svg> | |||
| <svg | |||
| v-if="innerclosed" | |||
| viewBox="0 0 15 15" | |||
| :fill="iconColors[1]" | |||
| style="vertical-align: top; color: #3c4047; height: 1em; width: 1em; padding-left: 2px;" | |||
| > | |||
| <path d="M0 14l6-6-6-6z"></path> | |||
| </svg> | |||
| </span> | |||
| <div class="content-wrap"> | |||
| <p :class="['first-line', length > 0 ? 'pointer' : '']" @click="toggleClose"> | |||
| <span v-if="jsonKey" class="json-key">"{{ jsonKey }}": </span> | |||
| <span v-if="length" | |||
| >{{ prefix }}{{ innerclosed ? "..." + subfix : "" }} | |||
| <span class="json-note">{{ innerclosed ? length + " items" : "" }}</span> | |||
| </span> | |||
| <span v-if="!length">{{ `${isArray ? "[]" : "{}"}${isLast ? "" : ","}` }}</span> | |||
| </p> | |||
| <div v-if="!innerclosed && length" class="json-body"> | |||
| <template v-for="(item, index) in items"> | |||
| <json-view | |||
| v-if="item.isJSON" | |||
| :key="index" | |||
| :closed="isClose()" | |||
| :data="item.value" | |||
| :json-key="item.key" | |||
| :current-deep="templateDeep + 1" | |||
| :deep="deep" | |||
| :icon-style="iconStyle" | |||
| :theme="theme" | |||
| :font-size="fontSize" | |||
| :line-height="lineHeight" | |||
| :icon-color="iconColors" | |||
| :is-last="index === items.length - 1" | |||
| :has-siblings="item.hasSiblings" | |||
| /> | |||
| <p v-else :key="index" class="json-item"> | |||
| <span class="json-key">{{ isArray ? "" : '"' + item.key + '":' }}</span> | |||
| <span :class="['json-value', getDataType(item.value)]"> | |||
| {{ | |||
| `${getDataType(item.value) === "string" ? '"' : ""}${formatValue(item.value)}${ | |||
| getDataType(item.value) === "string" ? '"' : "" | |||
| }${index === items.length - 1 ? "" : ","}` | |||
| }} | |||
| </span> | |||
| </p> | |||
| </template> | |||
| <span v-if="!innerclosed" class="base-line"></span> | |||
| </div> | |||
| <p v-if="!innerclosed" class="last-line"> | |||
| <span>{{ subfix }}</span> | |||
| </p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: "JsonView", | |||
| props: { | |||
| data: { | |||
| // 传入的json数据 | |||
| type: [Object, Array], | |||
| required: true | |||
| }, | |||
| jsonKey: { | |||
| // json的key值,用于第二层及二层以上的组件的key值 | |||
| type: String, | |||
| default: "" | |||
| }, | |||
| closed: { | |||
| // 是否折叠 | |||
| type: Boolean, | |||
| default: false | |||
| }, | |||
| isLast: { | |||
| //是否是最后一行 | |||
| type: Boolean, | |||
| default: true | |||
| }, | |||
| fontSize: { | |||
| //字体大小 | |||
| type: Number, | |||
| default: 14 | |||
| }, | |||
| lineHeight: { | |||
| //行高 | |||
| type: Number, | |||
| default: 24 | |||
| }, | |||
| deep: { | |||
| // 展开深度 | |||
| type: Number, | |||
| default: 3 | |||
| }, | |||
| currentDeep: { | |||
| // 当前为递归的第几层 | |||
| type: Number, | |||
| default: 1 | |||
| }, | |||
| iconStyle: { | |||
| // 折叠icon样式 | |||
| type: String, | |||
| default: "square" | |||
| }, | |||
| iconColor: { | |||
| //icon颜色 | |||
| type: Array, | |||
| default() { | |||
| return []; | |||
| } | |||
| }, | |||
| theme: { | |||
| // 主题 | |||
| type: String, | |||
| default: "" | |||
| }, | |||
| hasSiblings: { | |||
| // 是否有兄弟节点 | |||
| type: Boolean, | |||
| default: true | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| innerclosed: this.closed, | |||
| templateDeep: this.currentDeep, | |||
| visible: false | |||
| }; | |||
| }, | |||
| computed: { | |||
| isArray() { | |||
| return this.getDataType(this.data) === "array"; | |||
| }, | |||
| length() { | |||
| return this.isArray ? this.data.length : Object.keys(this.data).length; | |||
| }, | |||
| subfix() { | |||
| const data = this.data; | |||
| if (this.isEmptyArrayOrObject(data)) { | |||
| // 如果是空数组或空对象 | |||
| return ""; | |||
| } else { | |||
| return (this.isArray ? "]" : "}") + (this.isLast ? "" : ","); | |||
| } | |||
| }, | |||
| prefix() { | |||
| return this.isArray ? "[" : "{"; | |||
| }, | |||
| items() { | |||
| const json = this.data; | |||
| if (this.isArray) { | |||
| return json.map((item) => { | |||
| const isJSON = this.isObjectOrArray(item); | |||
| return { | |||
| value: item, | |||
| isJSON, | |||
| key: "" | |||
| }; | |||
| }); | |||
| } | |||
| return Object.keys(json).map((key) => { | |||
| const item = json[key]; | |||
| const isJSON = this.isObjectOrArray(item); | |||
| return { | |||
| value: item, | |||
| isJSON, | |||
| key | |||
| }; | |||
| }); | |||
| }, | |||
| iconColors() { | |||
| const { theme, iconColor } = this; | |||
| if (iconColor.length === 2) { | |||
| return iconColor; | |||
| } else { | |||
| if (theme === "one-dark") { | |||
| return ["#747983", "#747983"]; | |||
| } else if (theme === "vs-code") { | |||
| return ["#c6c6c6", "#c6c6c6"]; | |||
| } else { | |||
| return ["#747983", "#747983"]; | |||
| } | |||
| } | |||
| } | |||
| }, | |||
| watch: { | |||
| closed() { | |||
| this.innerclosed = this.closed; | |||
| } | |||
| }, | |||
| mounted() { | |||
| setTimeout(() => { | |||
| this.visible = true; | |||
| }, 0); | |||
| }, | |||
| methods: { | |||
| formatValue(data) { | |||
| if (data && data._isBigNumber) { | |||
| return data.toString(10); | |||
| } | |||
| return data; | |||
| }, | |||
| getDataType(data) { | |||
| return data && data._isBigNumber | |||
| ? "number" | |||
| : Object.prototype.toString | |||
| .call(data) | |||
| .slice(8, -1) | |||
| .toLowerCase(); | |||
| }, | |||
| isObjectOrArray(source) { | |||
| return ["array", "object"].includes(this.getDataType(source)); | |||
| }, | |||
| toggleClose() { | |||
| if (this.length === 0) { | |||
| return; | |||
| } | |||
| if (this.innerclosed) { | |||
| this.innerclosed = false; | |||
| } else { | |||
| this.innerclosed = true; | |||
| } | |||
| }, | |||
| isClose() { | |||
| return this.templateDeep + 1 > this.deep; | |||
| }, | |||
| isEmptyArrayOrObject(data) { | |||
| // 空数组或者空对象 | |||
| return [{}, []].map((item) => JSON.stringify(item)).includes(JSON.stringify(data)); | |||
| } | |||
| } | |||
| }; | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .json-view-container { | |||
| background-color: transparent; | |||
| &.deep-1 { | |||
| // overflow: auto; | |||
| padding-right: 10px; | |||
| } | |||
| .json-view { | |||
| position: relative; | |||
| display: block; | |||
| width: 100%; | |||
| height: 100%; | |||
| white-space: nowrap; | |||
| padding-left: 2rem; | |||
| box-sizing: border-box; | |||
| cursor: default; | |||
| .json-note { | |||
| color: #909399; | |||
| font-size: 12px; | |||
| font-style: italic; | |||
| } | |||
| .json-key { | |||
| color: #8c6325; | |||
| } | |||
| .json-value { | |||
| display: inline-block; | |||
| color: #57b73b; | |||
| word-break: break-all; | |||
| white-space: normal; | |||
| &.number { | |||
| color: #2d8cf0; | |||
| } | |||
| &.string { | |||
| color: #57b73b; | |||
| } | |||
| &.boolean { | |||
| color: #eb3324; | |||
| } | |||
| &.null { | |||
| color: #eb3324; | |||
| } | |||
| } | |||
| .json-item { | |||
| margin: 0; | |||
| padding-left: 2rem; | |||
| display: flex; | |||
| } | |||
| .first-line { | |||
| padding: 0; | |||
| margin: 0; | |||
| &.pointer { | |||
| cursor: pointer !important; | |||
| } | |||
| } | |||
| .json-body { | |||
| position: relative; | |||
| padding: 0; | |||
| margin: 0; | |||
| .base-line { | |||
| position: absolute; | |||
| height: 100%; | |||
| border-left: 1px dashed #bbb; | |||
| top: 0; | |||
| left: 2px; | |||
| &:hover { | |||
| } | |||
| } | |||
| } | |||
| .last-line { | |||
| padding: 0; | |||
| margin: 0; | |||
| } | |||
| .angle { | |||
| position: absolute; | |||
| display: block; | |||
| cursor: pointer; | |||
| float: left; | |||
| width: 20px; | |||
| text-align: center; | |||
| /*left: ~"calc(2rem - 18px)";*/ | |||
| left: 12px; | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @@ -0,0 +1,193 @@ | |||
| <template> | |||
| <div class="recommendPage"> | |||
| <swiper v-if="initOrNot" ref="videoSwiper" :options="swiperOption"> | |||
| <swiper-slide v-for="(item, index) in mediaNews" :key="index"> | |||
| <video | |||
| v-if="item.type === 1" | |||
| controls | |||
| muted="muted" | |||
| autoplay="autoplay" | |||
| class="multimedia" | |||
| style="width: 100%;object-fit: cover" | |||
| @ended="endVideo(index)" | |||
| > | |||
| <source :src="item.url" type="video/mp4" /> | |||
| </video> | |||
| <img v-else :src="item.url" class="multimedia" style="width: 100%;object-fit: cover" /> | |||
| </swiper-slide> | |||
| </swiper> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| import { swiper, swiperSlide } from "vue-awesome-swiper"; | |||
| import "swiper/dist/css/swiper.css"; | |||
| var timer; | |||
| export default { | |||
| name: "SwiperView", | |||
| components: { | |||
| swiper, | |||
| swiperSlide | |||
| }, | |||
| data() { | |||
| const files = require.context("@/assets/ads", true).keys(); | |||
| let ads = []; | |||
| console.log(ads); | |||
| for (let url in files) { | |||
| let temp = {}; | |||
| console.log("../assets/ads/" + files[url]); | |||
| temp.url = require("../assets/ads/" + files[url].substr(2)); | |||
| temp.type = 0; | |||
| if (files[url].endsWith("mp4")) { | |||
| temp.type = 1; | |||
| } | |||
| ads.push(temp); | |||
| } | |||
| return { | |||
| swiperOption: { | |||
| speed: 1000, | |||
| loop: false, | |||
| observer: true, | |||
| observeParents: true, | |||
| autoplayDisableOnInteraction: false, | |||
| allowTouchMove: false, | |||
| pagination: { | |||
| el: ".swiper-pagination", | |||
| clickable: true | |||
| }, | |||
| on: { | |||
| slideChangeTransitionEnd: () => { | |||
| this.slideChangeTransitionEndHandle(); | |||
| }, | |||
| slideChangeTransitionStart: () => { | |||
| this.slideChangeTransitionStartHandle(); | |||
| }, | |||
| //控制第一个slide切换 | |||
| init: () => { | |||
| this.initHandle(); | |||
| } | |||
| } | |||
| }, | |||
| initOrNot: false, | |||
| mediaLastIndex: 0, | |||
| mediaNews: ads | |||
| }; | |||
| }, | |||
| computed: { | |||
| swiper() { | |||
| return this.$refs.videoSwiper.swiper; | |||
| } | |||
| }, | |||
| watch: { | |||
| mediaNews: { | |||
| handler(newName, oldName) { | |||
| if (newName.length > 0) { | |||
| this.initOrNot = false; | |||
| this.$nextTick(() => { | |||
| this.initOrNot = true; | |||
| }); | |||
| } | |||
| }, | |||
| immediate: true, | |||
| deep: true | |||
| } | |||
| }, | |||
| mounted() {}, | |||
| methods: { | |||
| initHandle() { | |||
| let that = this; | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(function() { | |||
| let swiper = that.$refs.videoSwiper.swiper; | |||
| that.mediaNewsImgHandle(swiper); | |||
| }, 200); | |||
| }, | |||
| mediaNewsImgHandle(swiper) { | |||
| //刚切换到的activeIndex | |||
| let changePointActiveIndex = swiper.activeIndex; | |||
| if (swiper.activeIndex < this.mediaNews.length - 1) { | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(function() { | |||
| //要确认changePointActiveIndex是不是还是目前的activeIndex,是的话计时后执行,不是的话不执行 | |||
| if (changePointActiveIndex === swiper.activeIndex) { | |||
| swiper.slideNext(); | |||
| } | |||
| }, 5000); | |||
| } else { | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(function() { | |||
| if (changePointActiveIndex === swiper.activeIndex) { | |||
| swiper.slideTo(0, 0); | |||
| } | |||
| }, 5000); | |||
| } | |||
| }, | |||
| slideChangeTransitionStartHandle() { | |||
| let swiper = this.$refs.videoSwiper.swiper; | |||
| if (this.mediaNews[this.mediaLastIndex].type === 1) { | |||
| document.getElementsByClassName("multimedia")[this.mediaLastIndex].currentTime = 0; | |||
| } | |||
| }, | |||
| slideChangeTransitionEndHandle() { | |||
| console.log("end.."); | |||
| let that = this; | |||
| let swiper = that.$refs.videoSwiper.swiper; | |||
| if (this.mediaNews[swiper.activeIndex].type === 0) { | |||
| this.mediaNewsImgHandle(swiper); | |||
| } else { | |||
| if (this.mediaLastIndex.type === 1) { | |||
| document.getElementsByClassName("multimedia")[this.mediaLastIndex].pause(); | |||
| } | |||
| document.getElementsByClassName("multimedia")[swiper.activeIndex].removeAttribute("muted"); | |||
| document.getElementsByClassName("multimedia")[swiper.activeIndex].play(); | |||
| // this.playVideo(this.mediaNews[swiper.activeIndex].url); | |||
| } | |||
| this.mediaLastIndex = swiper.activeIndex; | |||
| }, | |||
| endVideo(index) { | |||
| let swiper = this.$refs.videoSwiper.swiper; | |||
| if (index === swiper.activeIndex) { | |||
| if (swiper.activeIndex < this.mediaNews.length - 1) { | |||
| swiper.slideNext(); | |||
| if (this.mediaNews[swiper.activeIndex].type === 1) { | |||
| document.getElementsByClassName("multimedia")[swiper.activeIndex].removeAttribute("muted"); | |||
| document.getElementsByClassName("multimedia")[swiper.activeIndex].play(); | |||
| // this.playVideo(this.mediaNews[swiper.activeIndex].url); | |||
| } | |||
| } else { | |||
| swiper.slideTo(0, 0); | |||
| if (this.mediaNews[swiper.activeIndex].type === 1) { | |||
| document.getElementsByClassName("multimedia")[swiper.activeIndex].removeAttribute("muted"); | |||
| document.getElementsByClassName("multimedia")[swiper.activeIndex].play(); | |||
| // this.playVideo(this.mediaNews[swiper.activeIndex].url); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| }; | |||
| </script> | |||
| <style> | |||
| .recommendPage .swiper-container { | |||
| position: relative; | |||
| width: 100%; | |||
| height: 1920px; | |||
| background: transparent; | |||
| } | |||
| .recommendPage .swiper-container .swiper-slide { | |||
| width: 100%; | |||
| //line-height: 1920px; | |||
| background: transparent; | |||
| color: #000; | |||
| font-size: 16px; | |||
| text-align: center; | |||
| } | |||
| swiper-slide img { | |||
| object-fit: contain; | |||
| } | |||
| </style> | |||
| @@ -0,0 +1,74 @@ | |||
| <template> | |||
| <div class="video-js-comp"> | |||
| <video ref="videoPlayer" class="video-js vjs-fluid" controls /> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| import videojs from "video.js"; | |||
| import "videojs-flash"; | |||
| import "video.js/dist/video-js.css"; | |||
| import CN from "video.js/dist/lang/zh-CN.json"; | |||
| videojs.addLanguage("zh-CN", CN); | |||
| export default { | |||
| name: "VideoPlayer", | |||
| props: { | |||
| options: { | |||
| type: Object, | |||
| default() { | |||
| return {}; | |||
| } | |||
| }, | |||
| dispose: { | |||
| type: Boolean, | |||
| required: true | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| player: null | |||
| }; | |||
| }, | |||
| watch: { | |||
| dispose(newVal) { | |||
| if (!newVal && this.player) { | |||
| this.player.dispose(); | |||
| } | |||
| } | |||
| }, | |||
| mounted() { | |||
| this.player = videojs(this.$refs.videoPlayer, this.options); | |||
| this.videoPlayer = this.$refs.videoPlayer; | |||
| console.log(this.player); | |||
| console.log(this.videoPlayer); | |||
| // 播放结束 | |||
| var that = this; | |||
| this.videoPlayer.addEventListener("ended", (e) => { | |||
| // 重置状态 | |||
| // this.videoVisiable = false; | |||
| that.$parent.setVideoVisible(false); | |||
| that.$parent.setTabindex(0); | |||
| that.$parent.enterImmerseMode(false); | |||
| }); | |||
| } | |||
| }; | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .video-js-comp { | |||
| width: 100%; | |||
| height: 100%; | |||
| position: relative; | |||
| overflow: hidden; | |||
| } | |||
| video { | |||
| display: block; | |||
| min-height: 100%; | |||
| min-width: 100%; | |||
| position: absolute !important; | |||
| top: 50% !important; | |||
| left: 50% !important; | |||
| transform: translate(-50%, -50%); | |||
| } | |||
| video:focus { | |||
| outline: none; | |||
| } | |||
| </style> | |||
| @@ -0,0 +1,68 @@ | |||
| export default { | |||
| qp: { | |||
| equip_no: "2", | |||
| set_no: "2", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开全屏" | |||
| }, | |||
| fhsy: { | |||
| equip_no: "2", | |||
| set_no: "1701", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "返回首页" | |||
| }, | |||
| zhts: { | |||
| equip_no: "2", | |||
| set_no: "103", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开综合态势" | |||
| }, | |||
| afts: { | |||
| equip_no: "2", | |||
| set_no: "104", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开安防态势" | |||
| }, | |||
| ryts: { | |||
| equip_no: "2", | |||
| set_no: "105", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开人员态势" | |||
| }, | |||
| tcts: { | |||
| equip_no: "2", | |||
| set_no: "106", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开停车态势" | |||
| }, | |||
| nyts: { | |||
| equip_no: "2", | |||
| set_no: "107", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开能源态势" | |||
| }, | |||
| xfts: { | |||
| equip_no: "2", | |||
| set_no: "108", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开消防态势" | |||
| }, | |||
| xmdsxt: { | |||
| equip_no: "1005", | |||
| set_no: "2", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开西门东侧摄像头" | |||
| }, | |||
| hys1bsxt: { | |||
| equip_no: "1005", | |||
| set_no: "3", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开一号会议室北侧摄像头" | |||
| }, | |||
| dtmxsxt: { | |||
| equip_no: "1005", | |||
| set_no: "4", | |||
| value: "AlarmCenter.ScreensAddin.ScreensCommand", | |||
| info: "打开大堂门口西侧摄像头" | |||
| } | |||
| }; | |||
| @@ -0,0 +1,80 @@ | |||
| export default { | |||
| appId: "xxxxx", | |||
| appSecret: "xxxxxxx", | |||
| /** | |||
| * @description 是否输出调试信息 | |||
| */ | |||
| isDebuggable: process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test", | |||
| /** | |||
| * @description api请求基础路径 | |||
| */ | |||
| baseUrl: process.env.VUE_APP_SERVER_URL, | |||
| /** | |||
| * CMS URL | |||
| */ | |||
| mediaApi: "http://127.0.0.1", | |||
| /** | |||
| * @description shop type | |||
| */ | |||
| shopType: Object.freeze({ | |||
| SHOP_DETAIL: 1, | |||
| SHOP_MAP: 2, | |||
| SHOP_LIST_ALL: 3, | |||
| SHOP_LIST_FOOD: 4, | |||
| SHOP_LIST_PLAY: 5, | |||
| SHOP_LIST_CLOTH: 6, | |||
| SHOP_LIST_KID: 7, | |||
| SHOP_LIST_ON_SALE: 8, | |||
| SHOP_LIST_ON_SERVICE: 9, | |||
| SHOP_LIST_ON_BEAUTY: 10 | |||
| }), | |||
| isPortrait: true, | |||
| storageKey: Object.freeze({ | |||
| KEY_SHOP_DATA: "preloadShopData" | |||
| }), | |||
| listItemType: Object.freeze({ | |||
| SHOP: 0, | |||
| CHAT: 1 | |||
| }), | |||
| appTitle: "奥北科技园", | |||
| username: "adminadmin", | |||
| userpwd: "admin.123", | |||
| // serverHj1: "http://192.168.1.254:8089", | |||
| getKeyUrl: "http://tx.lecooai.com:47880/api/server/getkey_pc", | |||
| serverHj: "http://dev.lecooai.com:47880", | |||
| // serverHj: "http://192.168.1.254:8089", | |||
| // serverHj: "http://39.105.85.176:63089", | |||
| mouseServerAb: "http://39.105.85.176:63091", | |||
| // serverDb: "http://39.105.85.176:63300", | |||
| serverDb: "http://192.168.1.254:13000", | |||
| padSocketUrl: "ws://192.168.124.4:9090", | |||
| // padSocketUrl: "ws://192.168.10.65:8666", | |||
| serverUrl: "http://192.168.10.65", | |||
| openDoorUrl: "http://39.105.85.176:63330", | |||
| serverPot: "/hj", | |||
| userType: { | |||
| mgr: 0, | |||
| emp: 1, | |||
| keyVisitor: 2, | |||
| courier: 3, | |||
| blackRole: 4, | |||
| visitor: 5 | |||
| }, | |||
| userTypeCn: { | |||
| 0: "高管", | |||
| 1: "员工", | |||
| 2: "VIP客户", | |||
| 3: "快递", | |||
| 4: "黑名单", | |||
| 5: "访客" | |||
| }, | |||
| debug: true, | |||
| faceDetectEnable: false, | |||
| detectSleep: 6000, | |||
| speakSleep: 60000, | |||
| returnAdPage: 30000, | |||
| currentScene: "lecoo1218" | |||
| }; | |||
| @@ -0,0 +1,19 @@ | |||
| var connection = require('./sql.js') | |||
| module.exports = { | |||
| query: (callback) => { | |||
| connection.query("select * from cmd order by created_at desc limit 20", function (error, results, fields) { | |||
| console.log(results) | |||
| callback(results); | |||
| }) | |||
| }, | |||
| add : (obj, callback) => { | |||
| connection.query('insert into cmd (question_id, question_text, answer) value (?, ?, ?)', [obj.id, obj.text, obj.answer], function (error, results) { | |||
| console.log(results) | |||
| callback(results); | |||
| }) | |||
| } | |||
| } | |||
| @@ -0,0 +1,90 @@ | |||
| const { add, query } = require("../db/dbHelp"); | |||
| const express = require("express"); | |||
| const router = express.Router(); | |||
| import Cloudia from "../api/cloudia-sdk-v1.4.1"; | |||
| // 连接数据库 | |||
| const jsonWrite = function(res, ret) { | |||
| if (typeof ret === "undefined") { | |||
| res.json({ | |||
| code: "1", | |||
| msg: "操作失败" | |||
| }); | |||
| } else { | |||
| res.json(ret); | |||
| } | |||
| }; | |||
| // 接口:增加信息sql,编辑修改信息sql1 | |||
| router.post("/save", (req, res) => { | |||
| const params = req.body; | |||
| add(params, (result) => { | |||
| jsonWrite(res, result); | |||
| }); | |||
| }); | |||
| // 接口:用户管理分页接口查询 | |||
| router.get("/getlist", (req, res) => { | |||
| const params = req.body; | |||
| console.log(params); | |||
| alert(JSON.stringify(Cloudia)); | |||
| alert("okokokok"); | |||
| query((result) => { | |||
| jsonWrite(res, result); | |||
| }); | |||
| }); | |||
| const db = require("../db/mssql"); //注意改路径 | |||
| router.get("/ms/detailMD", (req, res) => { | |||
| console.log(db.sql); | |||
| //根据时间查询的模板 | |||
| var count = 0; | |||
| var commonResult = []; | |||
| db.sql( | |||
| "SELECT PassType,count(1) as Count FROM HJ_PersonRecognition WHERE DateDiff(dd,DetectTime,getdate())=0 group by PassType order by PassType", | |||
| function(err, result) { | |||
| if (err) { | |||
| console.log(err); | |||
| return; | |||
| } | |||
| commonResult.push(...result.recordset); | |||
| count++; | |||
| if (count >= 3) { | |||
| res.send(commonResult); | |||
| } | |||
| } | |||
| ); | |||
| db.sql( | |||
| "select '0' as Reserve1, count(1) as cnt from HJ_PersonRecognition as person where person.Reserve1 = '0' and DATEDIFF(DAY, person.DetectTime, GETDATE()) = 0 union select '1' as Reserve1, count(1) as cnt from HJ_PersonRecognition as person where person.Reserve1 = '1' and DATEDIFF(DAY, person.DetectTime, GETDATE()) = 0", | |||
| function(err, result) { | |||
| if (err) { | |||
| console.log(err); | |||
| return; | |||
| } | |||
| commonResult.push(...result.recordset); | |||
| count++; | |||
| if (count >= 3) { | |||
| res.send(commonResult); | |||
| } | |||
| } | |||
| ); | |||
| db.sql( | |||
| "SELECT '0' as online, count(1) as num FROM HJ_EquipInfo WHERE Status = 1 and EquipTypeID = 3 union SELECT '1' as online, count(1) as num FROM HJ_EquipInfo WHERE (Status = 0 or Status = 2) and EquipTypeID = 3", | |||
| function(err, result) { | |||
| if (err) { | |||
| console.log(err); | |||
| return; | |||
| } | |||
| commonResult.push(...result.recordset); | |||
| count++; | |||
| if (count >= 3) { | |||
| res.send(commonResult); | |||
| } | |||
| } | |||
| ); | |||
| }); | |||
| module.exports = router; | |||
| @@ -0,0 +1,54 @@ | |||
| /* | |||
| mssql模块简单封装 | |||
| */ | |||
| const mssql = require("mssql"); | |||
| const db = {}; | |||
| const config = { | |||
| user: "sa", | |||
| password: "123456", //改成你自己的 | |||
| server: "192.168.1.254", //改成你自己的 | |||
| database: "Yifangzhongxin", //改成你自己的 | |||
| port: 1433, //改成你自己的 | |||
| options: { | |||
| encrypt: false // Use this if you're on Windows Azure | |||
| }, | |||
| pool: { | |||
| min: 0, | |||
| max: 10, | |||
| idleTimeoutMillis: 3000 | |||
| } | |||
| }; | |||
| //执行sql,返回数据. | |||
| db.sql = function(sql, callBack) { | |||
| const connection = new mssql.ConnectionPool(config, function(err) { | |||
| if (err) { | |||
| console.log(err); | |||
| return; | |||
| } | |||
| const ps = new mssql.PreparedStatement(connection); | |||
| ps.prepare(sql, function(err) { | |||
| if (err) { | |||
| console.log(err); | |||
| return; | |||
| } | |||
| ps.execute("", function(err, result) { | |||
| if (err) { | |||
| console.log(err); | |||
| return; | |||
| } | |||
| ps.unprepare(function(err) { | |||
| if (err) { | |||
| console.log(err); | |||
| callback(err, null); | |||
| return; | |||
| } | |||
| callBack(err, result); | |||
| }); | |||
| }); | |||
| }); | |||
| }); | |||
| }; | |||
| module.exports = db; | |||
| @@ -0,0 +1,10 @@ | |||
| var mysql = require("mysql"); | |||
| // 连接数据库 | |||
| var connection = mysql.createConnection({ | |||
| host: "39.105.85.176", | |||
| user: "root", | |||
| password: "Lecooai@2021", | |||
| database: "vue" | |||
| }); | |||
| module.exports = connection; | |||
| @@ -0,0 +1,44 @@ | |||
| import Vue from "vue"; | |||
| import App from "@/App.vue"; | |||
| import router from "@/router"; | |||
| import _ from "lodash/core"; | |||
| Vue.prototype._ = _; | |||
| import "@/plugins/lazyload"; | |||
| import "@/plugins/mintui"; | |||
| import Navigation from "vue-navigation"; | |||
| Vue.use(Navigation, { router }); | |||
| import Axios from "axios"; | |||
| Vue.prototype.$axios = Axios; | |||
| import ElementUI from "element-ui"; //element-ui的全部组件 | |||
| import "element-ui/lib/theme-chalk/index.css"; //element-ui的css | |||
| Vue.use(ElementUI); //使用elementUI | |||
| Vue.config.productionTip = false; | |||
| import jquery from "jquery"; | |||
| Vue.prototype.$ = jquery; | |||
| let app = null; | |||
| let count = 0; | |||
| function bindData() { | |||
| if (count == 1) { | |||
| app = new Vue({ | |||
| router, | |||
| render: (h) => h(App) | |||
| }).$mount("#app"); | |||
| global.vm = app; | |||
| } | |||
| } | |||
| Axios.get("./config.json").then((res) => { | |||
| if (res.data) { | |||
| count += 1; | |||
| Vue.prototype.$cmdList = res.data; | |||
| bindData(); | |||
| } | |||
| }); | |||
| export default Vue; | |||
| @@ -0,0 +1,284 @@ | |||
| import Config from "../config"; | |||
| import Cloudia from "../api/cloudia-sdk-v1.4.1"; | |||
| import { genPreRemoteReq, genRyts } from "../utils/genTtsText"; | |||
| import moment from "moment"; | |||
| let timer; | |||
| /** | |||
| * 通用的方法和一些与业务无关的工具方法 | |||
| * | |||
| */ | |||
| const mixin = { | |||
| data() { | |||
| return { | |||
| msg444: "hello" | |||
| }; | |||
| }, | |||
| methods: { | |||
| mixinMethod() { | |||
| console.log(this.$cmdList); | |||
| console.log(this.stateVal); | |||
| console.log(this.msgList); | |||
| // this.returnAdPage(); | |||
| console.log(this.msg444 + ",这是mixin混入方法"); | |||
| }, | |||
| setVideoVisible(visible) { | |||
| this.videoVisible = visible; | |||
| }, | |||
| setTabindex(tabIndex) { | |||
| this.tabIndex = tabIndex; | |||
| }, | |||
| playVideo(src) { | |||
| if (src) { | |||
| this.picVisible = false; | |||
| this.tabIndex = 5; | |||
| this.playerOptions = { | |||
| muted: false, | |||
| language: "zh-CN", | |||
| playbackRates: [0.5, 1.0, 1.5, 2.0], | |||
| autoplay: true, | |||
| controls: false, | |||
| sources: [ | |||
| { | |||
| type: "video/mp4", | |||
| src: src | |||
| } | |||
| ] | |||
| }; | |||
| this.videoVisible = true; | |||
| this.enterImmerseMode(true); | |||
| } else { | |||
| } | |||
| }, | |||
| playPic(src) { | |||
| if (src) { | |||
| this.videoVisible = false; | |||
| this.tabIndex = 5; | |||
| this.picUrl = src; | |||
| this.picVisible = true; | |||
| } | |||
| }, | |||
| setProgressCode(key) { | |||
| this.lastReq = key; | |||
| }, | |||
| sendMsg(type) { | |||
| // Cloudia.textTriggerNlp("人员态势"); | |||
| /*let obj = this.$cmdList["zhh_company_open"]; | |||
| obj.data.companyName = "道有道"; | |||
| console.log(obj);*/ | |||
| /*if (this.rotationY > 360) { | |||
| this.rotationY = 0.0; | |||
| } else { | |||
| this.rotationY += 0.2; | |||
| } | |||
| Cloudia.updateCharacterRotation(0.0, this.rotationY, 0.0);*/ | |||
| let obj = this.$cmdList["ry_open"]; | |||
| // obj.data.companyName = "道有道"; | |||
| var that = this; | |||
| genPreRemoteReq( | |||
| obj, | |||
| (result) => { | |||
| that.consoleLog("success=====1"); | |||
| console.log("success=====1"); | |||
| // that.consoleLog(JSON.stringify(result)); | |||
| var results = obj.msg.match(/#\[\w*]/g); | |||
| console.log(results); | |||
| obj.showMsg = obj.msg; | |||
| if (!obj.after_exec) { | |||
| for (var i in results) { | |||
| var temp = results[i]; | |||
| var iTemp = temp.replace("#[", ""); | |||
| iTemp = iTemp.replace("]", ""); | |||
| obj.showMsg = obj.showMsg.replace(temp, result.HttpData.data[iTemp]); | |||
| } | |||
| console.log(obj); | |||
| that.addMsgList(2, obj.showMsg); | |||
| } else { | |||
| console.log(that.$cmdList[obj.after_exec]); | |||
| let cobj = that.$cmdList[obj.after_exec]; | |||
| genPreRemoteReq( | |||
| cobj, | |||
| (result) => { | |||
| var results = cobj.msg.match(/#\[\w*]/g); | |||
| cobj.showMsg = cobj.msg; | |||
| for (var i in results) { | |||
| var temp = results[i]; | |||
| var iTemp = temp.replace("#[", ""); | |||
| iTemp = iTemp.replace("]", ""); | |||
| cobj.showMsg = cobj.showMsg.replace(temp, result.HttpData.data[iTemp]); | |||
| } | |||
| that.addMsgList(2, cobj.showMsg); | |||
| }, | |||
| (err) => { | |||
| console.log(err); | |||
| } | |||
| ); | |||
| } | |||
| }, | |||
| (res) => { | |||
| console.log("error======="); | |||
| that.consoleLog("error=====1"); | |||
| that.consoleLog(res); | |||
| // that.consoleLog(JSON.stringify(res)); | |||
| console.log(res); | |||
| } | |||
| ); | |||
| /*opendoor( | |||
| (res) => {}, | |||
| (err) => {} | |||
| );*/ | |||
| let a = "0"; | |||
| let b = 0; | |||
| /*alert(this._.isEqual(a, "" + b)); | |||
| alert(this._.isEqual("" + b, a)); | |||
| alert(a == b);*/ | |||
| this.consoleLog("skudhfishdifosijdknfknsdf"); | |||
| /*for (var i = 0; i < this.msgList.length; i++) { | |||
| if (this.msgList[i].from == type) { | |||
| this.msgList.splice(i, 1); | |||
| } | |||
| } | |||
| let text = | |||
| "奥北科技园由北京奥北兴华科贸中心有限公司投资开发,园区定位为“高端生态商务花园” 。项目总建筑面积约10.4万平方米,按照“中心绿化带串联起多个建筑”的规划构思,项目整体分为东、西、两个区域,东区为2栋甲级写字楼,西区为24栋小型花园式商务独栋办公楼 。"; | |||
| this.addMsgList(2, text);*/ | |||
| }, | |||
| fhsy(callback) { | |||
| var obj = this.$cmdList["fhsy"]; | |||
| genPreRemoteReq( | |||
| obj, | |||
| (res) => { | |||
| // that.addMsgList(2, obj.info); | |||
| callback(res); | |||
| }, | |||
| (res) => { | |||
| Cloudia.showLongToast(JSON.stringify(res)); | |||
| } | |||
| ); | |||
| }, | |||
| returnAdPage() { | |||
| /*this.tabIndex = 4; | |||
| // this.tabIndex = 0; | |||
| this.sleep = true; | |||
| this.isSpeaking = false; | |||
| this.lastReq = ""; | |||
| this.msgList = [ | |||
| { | |||
| from: 2, | |||
| message: "您好,我是小酷。" | |||
| } | |||
| ];*/ | |||
| Cloudia.setClothes("suit_blue"); | |||
| }, | |||
| leaveAdPage() { | |||
| this.tabIndex = 0; | |||
| // this.tabIndex = 0; | |||
| this.sleep = false; | |||
| Cloudia.setClothes("suit_blue"); | |||
| }, | |||
| enterImmerseMode(mode) { | |||
| Cloudia.enterImmerseMode(mode); | |||
| }, | |||
| showQrCode() { | |||
| this.imgQrcode = true; | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(function() { | |||
| Cloudia.playMotion("showRightHandTop"); | |||
| }, 1500); | |||
| }, | |||
| queryNlp() { | |||
| let that = this; | |||
| this.$axios.get(Config.serverDb + "/api/db/getlist", {}).then((res) => { | |||
| that.nplList = res.data; | |||
| }); | |||
| }, | |||
| changeCharacter() { | |||
| var characters = this.$cmdList["characters"]; | |||
| if (this.characterInd >= characters.length - 1) { | |||
| this.characterInd = 0; | |||
| } else { | |||
| this.characterInd++; | |||
| } | |||
| Cloudia.setCharacter(characters[this.characterInd]); | |||
| this.character = characters[this.characterInd]; | |||
| this.clothesInd = 0; | |||
| var clothes = this.$cmdList["clothes"][this.character]; | |||
| Cloudia.setClothes(clothes[this.clothesInd]); | |||
| }, | |||
| changeCloth() { | |||
| var clothes = this.$cmdList["clothes"][this.character]; | |||
| if (this.clothesInd >= clothes.length - 1) { | |||
| this.clothesInd = 0; | |||
| } else { | |||
| this.clothesInd++; | |||
| } | |||
| Cloudia.setClothes(clothes[this.clothesInd]); | |||
| }, | |||
| scrollMsgToBottom() { | |||
| this.tabIndex = 0; | |||
| let that = this; | |||
| this.$nextTick(() => { | |||
| let middle = that.$refs["middle"]; | |||
| if (middle) middle.scrollTop = middle.scrollHeight; | |||
| }); | |||
| }, | |||
| clickEvent() { | |||
| this.clickNum++; | |||
| if (this.clickNum >= 20) { | |||
| this.close(); | |||
| this.clickNum = 0; | |||
| // alert(this.clickNum); | |||
| } | |||
| if (this.clickNum >= 15) { | |||
| this.debug = !this.debug; | |||
| this.showMsg = !this.showMsg; | |||
| } | |||
| }, | |||
| _clearCache() { | |||
| localStorage.clear(); | |||
| }, | |||
| hiddenDebug() { | |||
| this.debug = false; | |||
| }, | |||
| containStr(array, text) { | |||
| for (var i = 0; i < array.length; i++) { | |||
| if (text.indexOf(array[i]) > -1) { | |||
| return array[i]; | |||
| } | |||
| } | |||
| return null; | |||
| }, | |||
| keysToArray(obj) { | |||
| var array = []; | |||
| for (var key in obj) { | |||
| array.push(key); | |||
| } | |||
| return array; | |||
| }, | |||
| consoleLog(text) { | |||
| let ts = new Date().getTime(); | |||
| this.consoleList = { | |||
| index: ts, | |||
| message: text, | |||
| time: moment(ts).format("mm:ss.SSS") | |||
| }; | |||
| }, | |||
| close() { | |||
| Cloudia.restartH5(); | |||
| } | |||
| } | |||
| }; | |||
| export default mixin; | |||
| @@ -0,0 +1,321 @@ | |||
| import Cloudia from "../api/cloudia-sdk-v1.4.1"; | |||
| import Config from "../config"; | |||
| import md5 from "js-md5"; | |||
| var timer; | |||
| const mixin_demo = { | |||
| data() { | |||
| return { | |||
| toast: "A Toast", | |||
| longToast: "A Long Toast", | |||
| tts: "1234567890", | |||
| bOffset: "0, 0, 0, 0", | |||
| cLocation: "-378.8,-0.7,448.3,false", | |||
| cRotation: "0,179.5,0,false", | |||
| motion: "bow", | |||
| wall: "Change BG Color", | |||
| wallRes: "3DRoom", | |||
| exp: "smile, 1", | |||
| mediaEvent: "playing", | |||
| asrWakeUp: true, | |||
| walkGreetEnable: true, | |||
| cameraMode: "level", | |||
| bgLocation: "1400,0,0", | |||
| setValueText: 12, | |||
| getValueText: 0, | |||
| ttsText: "成都天气", | |||
| testing: true, | |||
| iPlayTts: true, | |||
| iAsrWakeUp: true, | |||
| iGetRobotConfig: true, | |||
| iAppConfig: true, | |||
| iGetVolume: true, | |||
| allInterfaces: new Map(), | |||
| cloudiaEvents: new Map() | |||
| }; | |||
| }, | |||
| methods: { | |||
| getValidClass(cond) { | |||
| if (cond === undefined || cond === 0) { | |||
| return "api-layout interface-init"; | |||
| } else if (cond === 1) { | |||
| return "api-layout interface-success"; | |||
| } else { | |||
| return "api-layout interface-fail"; | |||
| } | |||
| }, | |||
| interfaceShowToast() { | |||
| let result = Cloudia.showToast(this.toast); | |||
| this.allInterfaces["interfaceShowToast"] = result ? 1 : 2; | |||
| }, | |||
| interfaceShowLongToast() { | |||
| let result = Cloudia.showLongToast(this.longToast); | |||
| this.allInterfaces["interfaceShowLongToast"] = result ? 1 : 2; | |||
| }, | |||
| interfacePlayTts() { | |||
| let result = Cloudia.playTts(this.tts); | |||
| if (result) { | |||
| this.iPlayTts = true; | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(() => { | |||
| this.iPlayTts = false; | |||
| this.allInterfaces["interfacePlayTts"] = this.cloudiaEvents["ttsPlay"] === 10 ? 1 : 2; | |||
| }, 1500); | |||
| } else { | |||
| this.allInterfaces["interfacePlayTts"] = 2; | |||
| } | |||
| }, | |||
| interfaceUpdateBrowserLocation() { | |||
| this.bOffset = this.bOffset.replace(/ /g, ""); | |||
| let offset = this.bOffset.split(","); | |||
| let result = Cloudia.updateBrowserLocation(offset[0], offset[1], offset[2], offset[3]); | |||
| this.allInterfaces["interfaceUpdateBrowserLocation"] = result ? 1 : 2; | |||
| }, | |||
| interfaceUpdateCharacterLocation() { | |||
| this.cLocation = this.cLocation.replace(/ /g, ""); | |||
| let location = this.cLocation.split(","); | |||
| let result = Cloudia.updateCharacterLocation(location[0], location[1], location[2], location[3]); | |||
| this.allInterfaces["interfaceUpdateCharacterLocation"] = result ? 1 : 2; | |||
| }, | |||
| interfaceUpdateCharacterRotation() { | |||
| this.cRotation = this.cRotation.replace(/ /g, ""); | |||
| let rotation = this.cRotation.split(","); | |||
| let result = Cloudia.updateCharacterRotation(rotation[0], rotation[1], rotation[2], rotation[3]); | |||
| this.allInterfaces["interfaceUpdateCharacterRotation"] = result ? 1 : 2; | |||
| }, | |||
| interfaceUpdateWallLocation() { | |||
| let result = Cloudia.setWallLocation(this.bgLocation); | |||
| this.allInterfaces["interfaceUpdateWallLocation"] = result ? 1 : 2; | |||
| }, | |||
| interfacePlayMotion() { | |||
| this.motion = this.motion.replace(/ /g, ""); | |||
| let params = this.motion.split(","); | |||
| let result; | |||
| if (params.length === 2) { | |||
| result = Cloudia.playMotion(params[0], params[1]); | |||
| } else { | |||
| result = Cloudia.playMotion(params[0]); | |||
| } | |||
| this.allInterfaces["interfacePlayMotion"] = result ? 1 : 2; | |||
| }, | |||
| interfaceSetBgWallColor() { | |||
| //通过使用 getElementById() 来访问 <color> 元素 | |||
| let colorEl = document.getElementById("color"); | |||
| console.info("selected color:" + colorEl.value); | |||
| let color = colorEl.value.replace("#", ""); | |||
| let r = parseInt(color.substring(0, 2), 16) / 255; | |||
| let g = parseInt(color.substring(2, 4), 16) / 255; | |||
| let b = parseInt(color.substring(4, 6), 16) / 255; | |||
| // console.info("Selected color: rgb(" + r + ", " + g + ", " + b + ")"); | |||
| let result = Cloudia.setBgWallColor(r + ", " + g + ", " + b); | |||
| this.allInterfaces["interfaceSetBgWallColor"] = result ? 1 : 2; | |||
| }, | |||
| interfaceSetBgWallRes() { | |||
| let result = Cloudia.setBgWallResource(this.wallRes); | |||
| this.allInterfaces["interfaceSetBgWallRes"] = result ? 1 : 2; | |||
| }, | |||
| interfaceGetDeviceId() { | |||
| let that = this; | |||
| this.iGetRobotConfig = true; | |||
| return Cloudia.getRobotInfoConfig("RobotId").then(function(ReturnValue) { | |||
| if (ReturnValue !== undefined && ReturnValue.ReturnValue !== undefined) { | |||
| that.deviceId = ReturnValue.ReturnValue; | |||
| } | |||
| that.allInterfaces["interfaceGetDeviceId"] = that.deviceId.length > 0 ? 1 : 2; | |||
| that.iGetRobotConfig = false; | |||
| }); | |||
| }, | |||
| interfaceGetAppConfig() { | |||
| let that = this; | |||
| this.iAppConfig = true; | |||
| return Cloudia.getAppConfig().then(function(ReturnValue) { | |||
| if (ReturnValue !== undefined && ReturnValue.ReturnValue !== undefined) { | |||
| that.appConfig = ReturnValue.ReturnValue; | |||
| } | |||
| that.allInterfaces["interfaceGetAppConfig"] = that.appConfig.length > 0 ? 1 : 2; | |||
| that.iAppConfig = false; | |||
| }); | |||
| }, | |||
| interfaceSetCharacter() { | |||
| let result = Cloudia.setCharacter(this.character); | |||
| this.allClothes = cloudiaConfig.allClothes; | |||
| this.clothes = this.allClothes[0]; | |||
| this.allInterfaces["interfaceSetCharacter"] = result ? 1 : 2; | |||
| return result; | |||
| }, | |||
| interfaceSetClothes() { | |||
| let result = Cloudia.setClothes(this.clothes); | |||
| this.allInterfaces["interfaceSetClothes"] = result ? 1 : 2; | |||
| }, | |||
| interfacePostMediaEvent() { | |||
| let result = Cloudia.postMediaEvent(this.mediaEvent); | |||
| this.allInterfaces["interfacePostMediaEvent"] = result ? 1 : 2; | |||
| }, | |||
| interfaceSetAsrWakeUpEnable() { | |||
| let result = Cloudia.setAsrWakeUpEnable(this.asrWakeUp); | |||
| if (result) { | |||
| this.iAsrWakeUp = true; | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(() => { | |||
| if (this.cloudiaEvents["asrWakeUp"] === this.asrWakeUp ? 10 : 20) { | |||
| this.allInterfaces["interfaceSetAsrWakeUpEnable"] = 1; | |||
| } else { | |||
| this.allInterfaces["interfaceSetAsrWakeUpEnable"] = 2; | |||
| } | |||
| this.iAsrWakeUp = false; | |||
| }, 1000); | |||
| } else { | |||
| this.allInterfaces["interfaceSetAsrWakeUpEnable"] = 2; | |||
| } | |||
| }, | |||
| interfaceStopPlayTts() { | |||
| let result = Cloudia.stopPlayTts(false); | |||
| this.allInterfaces["interfaceStopPlayTts"] = result ? 1 : 2; | |||
| }, | |||
| interfaceEnterImmerseMode() { | |||
| let result = Cloudia.enterImmerseMode(this.immerseMode); | |||
| this.allInterfaces["interfaceEnterImmerseMode"] = result ? 1 : 2; | |||
| }, | |||
| interfaceStartVideoTalk() { | |||
| let result = Cloudia.startVideoTalk(); | |||
| this.allInterfaces["interfaceStartVideoTalk"] = result ? 1 : 2; | |||
| }, | |||
| interfaceStopVideoTalk() { | |||
| let result = Cloudia.stopVideoTalk(); | |||
| this.allInterfaces["interfaceStopVideoTalk"] = result ? 1 : 2; | |||
| }, | |||
| interfaceSetVolume() { | |||
| let result = Cloudia.setVolume(this.setValueText); | |||
| this.allInterfaces["interfaceSetVolume"] = result ? 1 : 2; | |||
| }, | |||
| interfaceGetVolume() { | |||
| this.iGetVolume = true; | |||
| return Cloudia.getVolume().then((ReturnValue) => { | |||
| if (ReturnValue !== undefined && ReturnValue.ReturnValue !== undefined) { | |||
| this.getValueText = ReturnValue.ReturnValue; | |||
| console.info("========:" + this.getValueText + ", " + this.setValueText); | |||
| this.allInterfaces["interfaceGetVolume"] = | |||
| this.getValueText.toString() === this.setValueText.toString() ? 1 : 2; | |||
| } else { | |||
| this.allInterfaces["interfaceGetVolume"] = 2; | |||
| } | |||
| this.iGetVolume = false; | |||
| }); | |||
| }, | |||
| interfaceDownloadFiles() { | |||
| let result = Cloudia.downloadFiles( | |||
| "test", | |||
| JSON.stringify([ | |||
| { | |||
| name: "04070c61b7d40b5a90b98640645493cb.jpeg", | |||
| url: "https://127.0.0.1" | |||
| }, | |||
| { | |||
| name: "112350h4wcwa94c9ch3oth.jpg", | |||
| url: "https://127.0.0.1" | |||
| } | |||
| ]) | |||
| ); | |||
| this.allInterfaces["interfaceDownloadFiles"] = result ? 1 : 2; | |||
| }, | |||
| interfaceTextTriggerNlp() { | |||
| let result = Cloudia.textTriggerNlp(this.ttsText); | |||
| this.allInterfaces["interfaceTextTriggerNlp"] = result ? 1 : 2; | |||
| }, | |||
| loadAd() { | |||
| // TODO !!!!不同的环境需要切换不同的baseUrl!!!! | |||
| let baseUrl = "https://127.0.0.1"; | |||
| let timestamp = new Date().getTime(); | |||
| // TODO 填写你自己的appId | |||
| let appId = Config.appId; | |||
| let nonceStr = this.getRandomInt(1000, 9999); | |||
| // TODO 填写你自己的appSecret | |||
| let appSecret = Config.appSecret; | |||
| let sign = md5("appId" + appId + "timestamp" + timestamp + "nonceStr" + nonceStr + appSecret); | |||
| // console.info("appId:" + appId); | |||
| // console.info("appSecret:" + appSecret); | |||
| // console.info("sign:" + sign); | |||
| const headers = { | |||
| "Content-Type": "application/json", | |||
| appId: appId, | |||
| timestamp: timestamp, | |||
| nonceStr: nonceStr, | |||
| sign: sign | |||
| }; | |||
| let url = "/crss-robot/ads/robotapi/v1/adSpace/get?pageCode=home&robotCode=" + this.deviceId; | |||
| fetch(baseUrl + url, { headers }) | |||
| .then(async (response) => { | |||
| const data = await response.json(); | |||
| if (!response.ok) { | |||
| // get error message from body or default to response statusText | |||
| const error = (data && data.message) || response.statusText; | |||
| return Promise.reject(error); | |||
| } | |||
| console.info("load ad data success:" + JSON.stringify(data)); | |||
| if (data.code === 0 && data.data && data.data.adList) { | |||
| // 拼接完整URL | |||
| data.data.adList.map((e) => { | |||
| e.url = baseUrl + e.url; | |||
| }); | |||
| let adData = JSON.stringify(data.data.adList); | |||
| // 下载广告数据,下载成功之后会在event事件中收到通知 | |||
| Cloudia.downloadFiles("home", adData); | |||
| console.info("ad data:" + adData); | |||
| } else { | |||
| console.warn("ad data is empty"); | |||
| } | |||
| }) | |||
| .catch((error) => { | |||
| console.error("load ad data error:" + error); | |||
| }); | |||
| }, | |||
| interFun() { | |||
| var ii = "qp"; | |||
| this.handleCustomize(ii); | |||
| }, | |||
| insertNlp() { | |||
| this.addMsgList(2, "测试一下,测试一下"); | |||
| if (this.nplList.length > 10) { | |||
| this.nplList.splice(10, this.nplList.length - 10); | |||
| } | |||
| this.nplList = [ | |||
| { question_id: new Date().getTime(), question_text: "test test", answer: "answer....." }, | |||
| ...this.nplList | |||
| ]; | |||
| this.$axios | |||
| .post(Config.serverDb + "/api/db/save", { | |||
| id: new Date().getTime(), | |||
| text: "test test", | |||
| answer: "answer....." | |||
| }) | |||
| .then((res) => { | |||
| console.log(res); | |||
| }); | |||
| }, | |||
| queryNlp() { | |||
| let that = this; | |||
| this.$axios.get(Config.serverDb + "/api/db/getlist", {}).then((res) => { | |||
| that.nplList = res.data; | |||
| }); | |||
| }, | |||
| testAllInterface() { | |||
| let i = 0; | |||
| for (let [key, value] of this.allInterfaces) { | |||
| timer && clearTimeout(timer); | |||
| timer = setTimeout(() => { | |||
| this.testing = true; | |||
| try { | |||
| this[key](); | |||
| } catch (e) { | |||
| this.allInterfaces[key] = 2; | |||
| console.error("interface exec failed:" + key + ", " + value + "----" + e); | |||
| } | |||
| this.testing = false; | |||
| }, ++i * 1000); | |||
| } | |||
| } | |||
| } | |||
| }; | |||
| export default mixin_demo; | |||
| @@ -0,0 +1,156 @@ | |||
| import JsonView from "../components/JsonView"; | |||
| import videoPlayer from "../components/VideoView"; | |||
| import { Switch } from "mint-ui"; | |||
| import { swiper, swiperSlide } from "vue-awesome-swiper"; | |||
| import Config from "../config"; | |||
| import { handleFaceType } from "../utils/handleTts"; | |||
| let rec; //断线重连后,延迟5秒重新创建WebSocket连接 rec用来存储延迟请求的代码 | |||
| let isConnect = false; | |||
| const mixin_socket = { | |||
| components: { | |||
| JsonView, | |||
| videoPlayer, | |||
| swt: Switch, | |||
| swiper, | |||
| swiperSlide | |||
| }, | |||
| data() { | |||
| return { | |||
| webData: null, | |||
| lastDetectTs: 0, | |||
| lastPerson: {}, | |||
| lastPersonId: 0, | |||
| lastDetectObj: {}, | |||
| lastPersonTs: 0 | |||
| }; | |||
| }, | |||
| computed: {}, | |||
| mounted() { | |||
| if (Config.faceDetectEnable) { | |||
| this.initWebSocket(); | |||
| } | |||
| }, | |||
| destroyed() { | |||
| this.websock && this.websock.close(); | |||
| localStorage.clear(); | |||
| }, | |||
| methods: { | |||
| initWebSocket() { | |||
| const path = Config.padSocketUrl; // 后台给的websocket的ip地址 | |||
| this.websock = new WebSocket(path); | |||
| this.websock.onmessage = this.websocketOnMessage; | |||
| this.websock.onopen = this.websocketOnOpen; | |||
| this.websock.onerror = this.websocketOnError; | |||
| this.websock.onclose = this.websocketClose; | |||
| }, | |||
| reConnect() { | |||
| this.consoleLog("尝试重新连接"); | |||
| if (isConnect) return; //如果已经连上就不在重连了 | |||
| rec && clearTimeout(rec); | |||
| let that = this; | |||
| rec = setTimeout(function() { | |||
| // 延迟5秒重连 避免过多次过频繁请求重连 | |||
| that.initWebSocket(); | |||
| }, 5000); | |||
| }, | |||
| // 连接建立成功的信号 | |||
| websocketOnOpen() { | |||
| this.consoleLog("初始化成功"); // 连接成功后就可以在这里写一些回调函数了 | |||
| }, | |||
| // 连接建立失败重连 | |||
| websocketOnError() { | |||
| // 如果报错的话,在这里就可以重新初始化websocket,这就是断线重连 | |||
| // this.initWebSocket() | |||
| this.consoleLog("WebSocket连接发生错误"); | |||
| isConnect = false; //连接断开修改标识 | |||
| this.reConnect(); //连接错误 需要重连 | |||
| }, | |||
| // 数据接收 | |||
| websocketOnMessage(e) { | |||
| let that = this; | |||
| let obj = e.data; | |||
| if (typeof obj != "object") { | |||
| obj = JSON.parse(obj); | |||
| } | |||
| that.consoleLog( | |||
| "id=" + | |||
| (obj.id.length > 7 ? obj.id.substr(7) : obj.id) + | |||
| ",name=" + | |||
| obj.name + | |||
| ",tag=" + | |||
| obj.tag + | |||
| ",gender=" + | |||
| obj.gender | |||
| ); | |||
| // console.log(e.data); | |||
| //非说话的状态下,用户说完话两秒后 | |||
| let currentTs = new Date().getTime(); | |||
| if (!that.execLocked && !that.isSpeaking && that.lastReq == "" && currentTs - that.lastQTs > 2000) { | |||
| that.handleDetectedFace(obj); | |||
| } | |||
| }, | |||
| // 数据发送 | |||
| websocketSend(Data) { | |||
| if (typeof Data == "object") { | |||
| Data = JSON.stringify(Data); | |||
| } | |||
| this.consoleLog("send to serv:" + Data); | |||
| this.websock.send(Data); // Data变量就是你想对后台说些啥,根据后端给你的接口文档传值进行交互 | |||
| }, | |||
| // 关闭的信号 | |||
| websocketClose() { | |||
| this.consoleLog("断开连接,重试连接"); | |||
| isConnect = false; //连接断开修改标识 | |||
| this.reConnect(); //服务器主动断开的情况下,需要重连 | |||
| }, | |||
| handleDetectedFace(obj) { | |||
| let that = this; | |||
| let currentTs = new Date().getTime(); | |||
| let str = ""; | |||
| if (obj && obj.id == -1) { | |||
| //识别到脸 | |||
| that.lastDetectTs = currentTs; | |||
| that.leaveAdPage(); | |||
| setTimeout(function() { | |||
| that.playMotion("showLeftHand"); | |||
| }, 600); | |||
| return; | |||
| } else if (obj && obj.id > 0) { | |||
| //识别到人 | |||
| if (that.lastReq == "moshengren") { | |||
| that.lastReq = ""; | |||
| } | |||
| that.lastDetectTs = currentTs; | |||
| that.lastDetectObj = obj; | |||
| if (that.lastDetectObj.id === that.lastPerson.id) { | |||
| that.lastPerson.name = that.lastDetectObj.name; | |||
| that.lastPerson.tag = that.lastDetectObj.tag; | |||
| } | |||
| if ( | |||
| (obj.id == that.lastPersonId && (currentTs - that.lastPersonTs >= 15000 || that.sleep)) || | |||
| obj.id != that.lastPersonId | |||
| ) { | |||
| that.lastPersonId = obj.id; | |||
| that.lastPerson = obj; | |||
| str += handleFaceType(that, obj); | |||
| that.lastPersonTs = currentTs; | |||
| that.sleep = false; | |||
| that.tabIndex = 0; | |||
| that.addMsgList(2, str); | |||
| } | |||
| } | |||
| }, | |||
| noDetectedFace() { | |||
| let currentTs = new Date().getTime(); | |||
| if (currentTs - this.lastDetectTs > 5000) { | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| }; | |||
| export default mixin_socket; | |||
| @@ -0,0 +1,7 @@ | |||
| // 引入各种函数,便于做成npm包 | |||
| // indexedDB 部分 | |||
| import MetaHelp from './nf-meta/help.js' | |||
| export { | |||
| MetaHelp | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| import { reactive } from 'vue' | |||
| // 从json文件加载meta | |||
| import loadMetaFormJson from './loadmeta-json.js' | |||
| // 从 webSQL加载meta | |||
| import loadMetaFormSQL from './loadmeta-sql.js' | |||
| // 把meta存入 indexedDB | |||
| import { saveMetaAll, loadMeta } from './savemeta-db.js' | |||
| /** | |||
| * meta的help | |||
| * * 从 json 加载 meta,存入 indexedDB | |||
| * * 从 webSQL 加载 meta,存入 indexedDB | |||
| * * 从 indexedDB 加载 meta, | |||
| * * 把 meta 存入状态 | |||
| */ | |||
| export default class MetaHelp { | |||
| constructor (url) { | |||
| this.jsonUrl = url, // json 的路径,axios 加载用 | |||
| this.sqlHelp = null, // 访问 webSQL | |||
| this.dbHelp = null, // 访问 indexedDB | |||
| this.meta = reactive({ | |||
| menu: {}, | |||
| module: {}, | |||
| service: {} | |||
| }) | |||
| } | |||
| /** | |||
| * 从 indexedDB 里面加载 meta | |||
| * @returns | |||
| */ | |||
| async loadMetaFromDB() { | |||
| return await loadMeta(this.dbHelp) | |||
| } | |||
| /** | |||
| * 把 meta 存入 state | |||
| * @param {*} state 状态 | |||
| * @param {*} meta 要存入的 meta。menu:数组;module:对象;service:对象 | |||
| */ | |||
| toState(state, meta) { | |||
| // 存入菜单,需要去重 | |||
| meta.menu.forEach(_menu => { | |||
| if (state.menu.findIndex((m) => m.id === _menu.id) < 0) { | |||
| state.menu.push(_menu) | |||
| } | |||
| }) | |||
| // 存入模块 | |||
| Object.assign(state.module, meta.module) | |||
| // 存入服务 | |||
| Object.assign(state.service, meta.service) | |||
| } | |||
| /** | |||
| * 从 webSQL 加载 meta,然后存入 indexedDB,并且返回 meta | |||
| * @param {*} moduleId | |||
| */ | |||
| async sqlToDB(moduleId = null) { | |||
| console.log('MetaHelp 的 sqlToDB', this) | |||
| const meta = await loadMetaFormSQL(this.sqlHelp) | |||
| console.log('MetaHelp 的 SQL 读取出来的 meta ', meta) | |||
| // 遍历,添加到 indexedDB | |||
| saveMetaAll(this.dbHelp, meta) | |||
| return meta | |||
| } | |||
| /** | |||
| * 从 json 加载 meta,然后存入 indexedDB,并且返回 meta | |||
| * @param {*} moduleId 模块ID | |||
| * @returns | |||
| */ | |||
| async loagMetaFromJson(moduleId = null) { | |||
| console.log('MetaHelp 的 sqlToDB', this) | |||
| const meta = await loadMetaFormJson(this.jsonUrl) | |||
| console.log('MetaHelp 的 从json加载的meta:', meta) | |||
| // 遍历,添加到 indexedDB | |||
| saveMetaAll(this.dbHelp, meta) | |||
| return meta | |||
| } | |||
| } | |||
| @@ -0,0 +1,135 @@ | |||
| // axios | |||
| import axios from 'axios' | |||
| /** | |||
| * 加载 json 文件 整理成 meta 的格式,返回 | |||
| */ | |||
| /** | |||
| * 01 获取 json文件 的目录,因为json文件比较多,还希望实现热更新,所以做了个加载目录。 | |||
| * * 应该加个随机数,便于即使更新。 | |||
| * * 因为有缓存,所以不用怕过多访问的问题。 | |||
| */ | |||
| const _loadFileDirectory = (jsonURL) => { | |||
| return new Promise((resolve, reject) => { | |||
| const _url = `${jsonURL}/dir.json?v=1` | |||
| axios.get(_url).then((res) => { | |||
| // console.log('dir -- 目录:', res) | |||
| resolve(res.data) | |||
| }).catch((res) => { | |||
| reject(res) | |||
| }) | |||
| }) | |||
| } | |||
| /** | |||
| * 整理加载的json,转成meta格式 | |||
| */ | |||
| const _format = (res) => { | |||
| const meta = { | |||
| service: {}, | |||
| module: {}, | |||
| menu: res[0].data.menu | |||
| } | |||
| // 遍历meta,进行分类 | |||
| res.forEach((re, index) => { | |||
| if (index === 0) return // 第一个是菜单, | |||
| const model = re.data | |||
| if (typeof model.actions !== 'undefined') { | |||
| // 后端API | |||
| meta.service[model.moduleId] = model | |||
| } else { | |||
| // 模块的 meta | |||
| if (typeof meta.module[model.moduleId] === 'undefined') { | |||
| meta.module[model.moduleId] = { | |||
| moduleId: model.moduleId | |||
| } | |||
| } | |||
| // 开始判断 | |||
| if (typeof model.btnOrder === 'object') { | |||
| // 按钮 | |||
| meta.module[model.moduleId].button = model | |||
| } else if (typeof model.quickFind === 'object') { | |||
| // 查询 | |||
| meta.module[model.moduleId].find = model | |||
| } else if (typeof model.idName === 'string') { | |||
| // 列表 | |||
| meta.module[model.moduleId].grid = model | |||
| } else if (typeof model.formId !== 'undefined') { | |||
| // 表单 | |||
| if (typeof meta.module[model.moduleId].forms === 'undefined') { | |||
| meta.module[model.moduleId].forms = {} | |||
| } | |||
| meta.module[model.moduleId].forms[model.formId] = model | |||
| } | |||
| } | |||
| }) | |||
| return meta | |||
| } | |||
| /** | |||
| * axios 读取json文件,然后返回 | |||
| * @param {*} josnDir 前端模块meta 的文件夹 | |||
| * @param {*} serviveDir 后端服务meta 的文件夹 | |||
| * @param {*} jsonURL 项目meta的url | |||
| * @returns | |||
| */ | |||
| const _loadMeta = (josnDir, serviveDir, jsonURL) => { | |||
| return new Promise((resolve, reject) => { | |||
| const actionName = ['button', 'find', 'grid'] | |||
| // 加载json的 请求的 数组,交给 Promise.all 使用 | |||
| const getMetaAxios = [] | |||
| // 加入导航菜单 | |||
| const _url = `${jsonURL}/menu.json` | |||
| getMetaAxios.push(axios.get(_url)) | |||
| // 前端meta 请求 加入数组 | |||
| for (const key in josnDir) { | |||
| const meta = josnDir[key] // 模块需要的表单 | |||
| // 添加按钮、列表、查询 | |||
| actionName.forEach(action => { | |||
| const _url = `${jsonURL}module/${key}/${action}.json` | |||
| getMetaAxios.push(axios.get(_url)) | |||
| }) | |||
| // 添加表单 | |||
| meta.forEach(form => { | |||
| const _url = `${jsonURL}module/${key}/${form}.json` | |||
| getMetaAxios.push(axios.get(_url)) | |||
| }) | |||
| } | |||
| // 后端API的meta 请求,也加入数组 | |||
| serviveDir.forEach(api => { | |||
| const _url = `${jsonURL}service/${api}.json` | |||
| getMetaAxios.push(axios.get(_url)) | |||
| }) | |||
| // 一起发起所有json文件的请求 | |||
| Promise.all(getMetaAxios).then((res) => { | |||
| // console.log('data:', res) | |||
| if (res[0].status === 200) { // statusText | |||
| // json 数据 转换成 meta 格式 | |||
| const meta = _format(res) | |||
| console.log('----json--处理好后的--meta:--', meta) | |||
| // 返回 meta | |||
| resolve(meta) | |||
| } | |||
| }) | |||
| }) | |||
| } | |||
| /** | |||
| * 加载josn文件,整理后变成meta格式 | |||
| * @param {string} jsonURL 项目meta的url | |||
| * @returns 整理好的meta | |||
| */ | |||
| const loadMetaFormJson = async (jsonURL) => { | |||
| // 获取json的文件目录,便于 axios 加载 | |||
| const dir = await _loadFileDirectory(jsonURL) | |||
| return await _loadMeta(dir.jsonDir, dir.serviceDir, jsonURL) | |||
| } | |||
| export default loadMetaFormJson | |||
| @@ -0,0 +1,206 @@ | |||
| /** | |||
| * 从 SQL 里面加载数据,整理成 meta 的格式 | |||
| */ | |||
| /** | |||
| * 把 webSQL 里的【菜单】数据变成 meta 的格式 | |||
| */ | |||
| const _getMenuMetaBySQL = (data) => { | |||
| const menu = [] | |||
| data.forEach(m => { | |||
| menu.push({ | |||
| id: m.moduleId, | |||
| componentKind: m.componentKind, | |||
| icon: m.icon, | |||
| moduleLevel: m.moduleLevel, | |||
| parentId: m.parentId, | |||
| title: m.title | |||
| }) | |||
| }) | |||
| return menu | |||
| } | |||
| /** | |||
| * 把 webSQL 里的【按钮】数据变成 meta 的格式 | |||
| */ | |||
| const _getButtonMetaBySQL = (data) => { | |||
| const meta = { | |||
| moduleId: data.moduleId, | |||
| btnOrder: [], | |||
| itemMeta: {} | |||
| } | |||
| data.forEach(btn => { | |||
| meta.btnOrder.push(btn.buttonId) | |||
| meta.itemMeta[btn.buttonId] = btn | |||
| }) | |||
| return meta | |||
| } | |||
| /** | |||
| * 把 webSQL 里的【列表】数据变成 meta 的格式 | |||
| */ | |||
| const _getGridMetaBySQL = (grid, item) => { | |||
| const meta = grid[0] | |||
| meta.colOrder = meta.colOrder.split(',') | |||
| meta.itemMeta = {} | |||
| // meta.quickFind = meta.quickFind | |||
| item.forEach(ctl => { | |||
| // meta.colOrder.push(ctl.columnId) | |||
| meta.itemMeta[ctl.columnId] = ctl | |||
| }) | |||
| return meta | |||
| } | |||
| /** | |||
| * 把 webSQL 里的【查询】数据变成 meta 的格式 | |||
| */ | |||
| const _getFindMetaBySQL = (find, item) => { | |||
| const meta = find[0] | |||
| meta.allFind = meta.allFind.split(',') | |||
| meta.quickFind = meta.quickFind.split(',') | |||
| meta.itemMeta = {} | |||
| item.forEach(ctl => { | |||
| // meta.quickFind.push(ctl.columnId) | |||
| // meta.allFind.push(ctl.columnId) | |||
| meta.itemMeta[ctl.columnId] = ctl | |||
| }) | |||
| return meta | |||
| } | |||
| /** | |||
| * 把 webSQL 里的【表单】数据变成 meta 的格式 | |||
| * * form 数组,包含多个 formId | |||
| */ | |||
| const _getFormMetaBySQL = (forms, items) => { | |||
| const meta = {} | |||
| forms.forEach(fm => { | |||
| meta[fm.formId] = fm | |||
| meta[fm.formId].colOrder = meta[fm.formId].colOrder.split(',') | |||
| meta[fm.formId].itemMeta = {} | |||
| items.filter(a => a.formId === fm.formId).forEach(ctl => { | |||
| meta[fm.formId].itemMeta[ctl.columnId] = ctl | |||
| }) | |||
| }) | |||
| return meta | |||
| } | |||
| /** | |||
| * 把 webSQL 里的【actions】数据变成 meta 的格式 | |||
| */ | |||
| const _getActionMetaBySQL = (data) => { | |||
| const actions = {} | |||
| data.forEach(action => { | |||
| actions[action.actionId] = { | |||
| actionName: action.actionName, | |||
| kind: action.kind, | |||
| model: action.modelId | |||
| } | |||
| }) | |||
| return actions | |||
| } | |||
| /** | |||
| * 把 webSQL 里的【models】数据变成 meta 的格式 | |||
| */ | |||
| const _getModelMetaBySQL = (data) => { | |||
| const models = {} | |||
| data.forEach(model => { | |||
| models[model.actionId] = { | |||
| tableName: model.tableName, | |||
| idKey: model.idKey, | |||
| cols: model.cols, | |||
| pager: { | |||
| orderBy: { roleId: false }, | |||
| pagerIndex: 1, | |||
| pagerSize: model.pagerSize, | |||
| pagerTotal: 100 | |||
| }, | |||
| query: {} | |||
| } | |||
| }) | |||
| return models | |||
| } | |||
| /** | |||
| * 开发模式:从 webSQL 读取数据,转换成meta 的格式 | |||
| * * 菜单meta、模块meta、service的meta | |||
| * * 从 SQL 加载数据,转换格式,返回。 | |||
| */ | |||
| const loadMetaFormSQL = async (sqlHelp) => { | |||
| console.log('------webSQL 的 sqlHelp', sqlHelp) | |||
| const tables = sqlHelp._tables | |||
| // 存放 SQL 里面的 meta | |||
| const meta = {} | |||
| // 获取所有数据库里的 meta 数据 | |||
| for (const key in tables) { | |||
| const tt = tables[key] | |||
| const tmp = await tt.list() | |||
| meta[key] = Array.from(tmp) | |||
| } | |||
| console.log('------controller 的 meta', meta) | |||
| // 返回的 meta | |||
| const reMeta = { | |||
| menu: _getMenuMetaBySQL(meta.nf_module), // 记录菜单 | |||
| module: {}, // 模块 | |||
| service: {} // service | |||
| } | |||
| const _tmp = (name, modId) => { | |||
| return meta[name].filter((a) => a.moduleId === modId) | |||
| } | |||
| // 遍历菜单,变成 meta 的格式 | |||
| for (let i = 0; i < meta.nf_module.length; i++) { | |||
| const modId = meta.nf_module[i].moduleId | |||
| const __moduleMeta = { // 记录模块的meta | |||
| moduleId: modId, | |||
| pager: {}, | |||
| button: {}, | |||
| grid: {}, | |||
| find: {}, | |||
| forms: {} | |||
| } | |||
| // 分页 | |||
| // __moduleMeta.pager = this._getButtonMetaBySQL(meta[151].filter((a) => a.moduleId === modId)) | |||
| // 列表 | |||
| __moduleMeta.grid = _getGridMetaBySQL(_tmp('v_module_grid', modId), _tmp('v_module_grid_item', modId)) | |||
| // 按钮 | |||
| __moduleMeta.button = _getButtonMetaBySQL(_tmp('v_module_button', modId)) | |||
| // 查询 | |||
| __moduleMeta.find = _getFindMetaBySQL(_tmp('v_module_find', modId), _tmp('v_module_find_item', modId)) | |||
| // 表单 | |||
| __moduleMeta.forms = _getFormMetaBySQL(_tmp('v_module_form', modId), _tmp('v_module_form_item', modId)) | |||
| // 记录 | |||
| reMeta.module[modId] = __moduleMeta | |||
| } | |||
| // 遍历service,整理后端api | |||
| for (let i = 0; i < meta.v_service.length; i++) { | |||
| const service = meta.v_service[i] | |||
| const serviceId = service.serviceId | |||
| // 记录service | |||
| const serviceMeta = { | |||
| moduleId: serviceId, | |||
| moduleName: service.serviceName, | |||
| actions: {}, | |||
| models: {} | |||
| } | |||
| const _tmp = (id) => { | |||
| return meta[id].filter((a) => a.serviceId === serviceId) | |||
| } | |||
| serviceMeta.actions = _getActionMetaBySQL(_tmp('v_service_action', serviceId)) | |||
| serviceMeta.models = _getModelMetaBySQL(_tmp('v_service_model', serviceId)) | |||
| reMeta.service[serviceId] = serviceMeta | |||
| } | |||
| // 返回整理好的 meta | |||
| return reMeta | |||
| } | |||
| export default loadMetaFormSQL | |||
| @@ -0,0 +1,100 @@ | |||
| /** | |||
| * saveMeta:把 meta 的一个属性 存入 indexedDB 的一个对象仓库 | |||
| * saveMetaAll:把 meta 存入 indexedDB | |||
| * loadMeta:从 indexedDB 加载meta | |||
| */ | |||
| /** | |||
| * json、webSQL 的 meta,存入 indexedDB | |||
| * @param {help} help 访问 indexedDB 的 help | |||
| * @param {string} storeName 仓库名称 | |||
| * @param {object} meta 要存入的对象,对象集合 | |||
| * @returns 仅通知 | |||
| */ | |||
| const saveMeta = (help, storeName, meta) => { | |||
| const idName = { // 主键名称的字典 | |||
| menuMeta: 'id', | |||
| moduleMeta: 'moduleId', | |||
| serviceMeta: 'moduleId' | |||
| } | |||
| return new Promise((resolve, reject) => { | |||
| let count = 0 | |||
| help.beginInit(storeName).then((store) => { | |||
| count += Object.keys(meta).length | |||
| if (count === 0) { | |||
| resolve(null) | |||
| } | |||
| for (const key in meta) { | |||
| // 先判断有没有,没有add;有了put | |||
| store.get(meta[key][idName[storeName]]) | |||
| .onsuccess = (event) => { | |||
| // console.log('====== 要添加的key:', storeName + '_' + meta[key][idName[storeName]]) | |||
| // console.log('====== 获取的 结果:', event.target.result) | |||
| if (typeof event.target.result === 'undefined') { | |||
| // 添加 | |||
| store.add(meta[key]) // 添加一条meta | |||
| .onsuccess = (event) => { | |||
| count -= 1 | |||
| if (count === 0) { | |||
| resolve(event.target.result) | |||
| } | |||
| } | |||
| } else { | |||
| // 修改 | |||
| store.put(meta[key]) // 修改一条meta | |||
| .onsuccess = (event) => { | |||
| count -= 1 | |||
| if (count === 0) { | |||
| resolve(event.target.result) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| }) | |||
| }) | |||
| } | |||
| /** | |||
| * 把 meta 存入 indexedDB | |||
| * @param {*} help indexedDB 的 help | |||
| * @param {*} meta 要存入的 meta | |||
| */ | |||
| const saveMetaAll = async (help, meta) => { | |||
| await saveMeta(help, 'serviceMeta', meta.service) | |||
| await saveMeta(help, 'moduleMeta', meta.module) | |||
| await saveMeta(help, 'menuMeta', meta.menu) | |||
| } | |||
| /** | |||
| * 从 indexedDB 里面加载 meta,并且返回 | |||
| * @param {*} help indexedDB 的 help | |||
| * @returns | |||
| */ | |||
| const loadMeta = async (help) => { | |||
| const state = { | |||
| menu: [], | |||
| module: {}, | |||
| service: {} | |||
| } | |||
| state.menu = await help.getModel('menuMeta') | |||
| const _module = await help.getModel('moduleMeta') | |||
| const _service = await help.getModel('serviceMeta') | |||
| for (const key in _module) { | |||
| const m = _module[key] | |||
| state.module[m.moduleId] = m | |||
| } | |||
| for (const key in _service) { | |||
| const s = _service[key] | |||
| state.service[s.moduleId] = s | |||
| } | |||
| return state | |||
| } | |||
| export { | |||
| saveMetaAll, // 存入 meta | |||
| saveMeta, // 存入一个属性 | |||
| loadMeta // 加载 meta | |||
| } | |||
| @@ -0,0 +1,116 @@ | |||
| /** | |||
| * 一般查询方式的字典 | |||
| */ | |||
| const _find = { | |||
| 401: (colValue, key) => colValue === key, // = | |||
| 403: (colValue, key) => colValue.includes(key), // 包含 | |||
| 405: (colValue, key) => colValue.indexOf(key) === 0, // 起始于 | |||
| 406: (colValue, key) => colValue.indexOf(key) + key.length === colValue.length, // 结束于 | |||
| 413: (colValue, key) => colValue > key, // > | |||
| 414: (colValue, key) => colValue >= key, // >= | |||
| 415: (colValue, key) => colValue < key, // < | |||
| 416: (colValue, key) => colValue <= key, // <= | |||
| 417: (colValue, key) => key[0] <= colValue && colValue <= key[1], // between | |||
| 418: (colValue, key) => key[0] < colValue && colValue <= key[1], // a < x <= b | |||
| 419: (colValue, key) => key[0] <= colValue && colValue < key[1], // a <= x < b | |||
| 420: (colValue, key) => key[0] < colValue && colValue < key[1] // a < x < b | |||
| } | |||
| /** | |||
| * IDBKeyRange 的字典 | |||
| */ | |||
| const _dicRange = { | |||
| 401: (_value) => IDBKeyRange.only(_value), // = | |||
| // 403: (_value) => IDBKeyRange.only(_value), | |||
| // 405: (_value) => IDBKeyRange.only(_value), | |||
| // 406: (_value) => IDBKeyRange.only(_value), | |||
| 413: (_value) => IDBKeyRange.lowerBound(_value, true), // > | |||
| 414: (_value) => IDBKeyRange.lowerBound(_value), // >= | |||
| 415: (_value) => IDBKeyRange.upperBound(_value, true), // < | |||
| 416: (_value) => IDBKeyRange.upperBound(_value), // <= | |||
| 417: (_value) => IDBKeyRange.bound(_value[0], _value[1]), // between | |||
| 418: (_value) => IDBKeyRange.bound(_value[0], _value[1], true, false), // a < x <= b | |||
| 419: (_value) => IDBKeyRange.bound(_value[0], _value[1], false, true), // a <= x < b | |||
| 420: (_value) => IDBKeyRange.bound(_value[0], _value[1], true, true) // a < x < b | |||
| } | |||
| // 索引的排序方式,正序、倒序 | |||
| // const _description = page.description || 'prev' // 默认倒序 | |||
| /** | |||
| * 遍历查询条件,找到对应的字段,做判断,有一个不符合就返回 false | |||
| * @param {*} other 查询条件 | |||
| * @param {*} model 要核对的对象 | |||
| * @returns 是否符合 | |||
| */ | |||
| const _check = (other, model) => { | |||
| let re = true | |||
| for (const key in other) { | |||
| const colValue = model[key] // 被查询的内容 | |||
| const kind = other[key][0] // 查询方式 | |||
| const _key = other[key][1] // 查询条件的值 | |||
| const _re = _find[kind](colValue, _key) // 验证 | |||
| if (!_re) re = false | |||
| } | |||
| return re | |||
| } | |||
| /** | |||
| * 处理索引和其他查询 | |||
| * @param {*} indexNames 对象仓库已经设置的索引 | |||
| * @param {*} query 查询条件 | |||
| * @returns IDBKeyRange、其他查询条件、查询方式、回调查询 | |||
| */ | |||
| const _toIndex = (indexNames, query) => { | |||
| const re = { | |||
| range: null, | |||
| other: {}, | |||
| find: (other, model) => _check(other, model), // 查询非索引字段 | |||
| callback: () => {} // 回调查询,可以自定义查询方式 | |||
| } | |||
| // 匹配到的索引字段 | |||
| let indexName = '' | |||
| // 查询条件字段和索引字段,匹配一下,只匹配第一个索引字段 | |||
| for (let i = 0; i < indexNames.length; i++) { | |||
| // 索引字段名称 | |||
| const _indexName = indexNames[i] | |||
| if (typeof query[_indexName] !== 'undefined') { | |||
| // 查询方式 | |||
| const _kind = query[_indexName][0] | |||
| // 查询的值 | |||
| const _value = query[_indexName][1] | |||
| // 查询条件里包含索引,记录,后面的就不管了。 | |||
| // 匹配查询方式 | |||
| re.range = _dicRange[_kind * 1](_value) | |||
| // 没有的话,说明无法利用索引 | |||
| if (typeof re.range === 'undefined') { | |||
| re.range = null | |||
| } else { | |||
| indexName = _indexName | |||
| } | |||
| } | |||
| if (indexName !== '') { | |||
| // 退出循环 | |||
| i = indexNames.length | |||
| } | |||
| } | |||
| // 把其他的查询字段放在 other 里面 | |||
| for (const key in query) { | |||
| const _query = query[key] | |||
| if (indexName !== key) { | |||
| // 记录到其他查询条件里面 | |||
| re.other[key] = _query | |||
| } | |||
| } | |||
| return re | |||
| } | |||
| export default _toIndex | |||
| @@ -0,0 +1,19 @@ | |||
| import { unref, isReactive, toRaw } from 'vue' | |||
| // 内部函数,如果是proxy,那么获取原型,否则会报错。 | |||
| const _vueToObject = (obj) => { | |||
| /* | |||
| // 处理 ref | |||
| let _object = unref(obj) | |||
| // 处理 reactive | |||
| if (isReactive(_object)) { | |||
| // 如果是 vue 的 reactive 类型,那么获取原型,否则会报错 | |||
| _object = toRaw(_object) | |||
| } | |||
| */ | |||
| const tmp = unref(obj) | |||
| const _object = isReactive(tmp) ? toRaw(tmp): tmp | |||
| return _object | |||
| } | |||
| export default _vueToObject | |||
| @@ -0,0 +1,26 @@ | |||
| /** | |||
| * 初始化数据的时候使用的一个事务。 | |||
| * * help._db 必然可用,不用判断。 | |||
| */ | |||
| const beginInit = (help, storeName) => { | |||
| return new Promise((resolve, reject) => { | |||
| // | |||
| const tranRequest = help._db.transaction(storeName, 'readwrite') | |||
| const store = tranRequest.objectStore(storeName) // 获取store | |||
| tranRequest.onerror = (event) => { | |||
| console.log('读写事务出错:', event.target.error) | |||
| // eslint-disable-next-line prefer-promise-reject-errors | |||
| reject('读写事务出错:' + event.target.error) | |||
| // tranRequest.abort() // 大概是回滚的意思。 | |||
| } | |||
| tranRequest.oncomplete = (event) => { | |||
| // console.log('初始化数据事务完毕:', window.performance.now(), help._dataState) | |||
| // help._dataState = 'done' | |||
| } | |||
| resolve(store) | |||
| }) | |||
| } | |||
| export default beginInit | |||
| @@ -0,0 +1,32 @@ | |||
| /** | |||
| * 开启一个读写的事务。需要判断 help._db 是否可用 | |||
| * @param {*} help indexedDB 的 help | |||
| * @param {Array} storeName 字符串的数组,对象仓库的名称 | |||
| * @param {string} type readwrite:读写事务;readonly:只读事务;versionchange:允许执行任何操作,包括删除和创建对象存储和索引。 | |||
| * @returns 读写事务 | |||
| */ | |||
| const beginTran = (help, storeName, type = 'readwrite') => { | |||
| return new Promise((resolve, reject) => { | |||
| const _tran = () => { | |||
| const tranRequest = help._db.transaction(storeName, type) | |||
| tranRequest.onerror = (event) => { | |||
| const err = `${type} 事务出错:${event.target.error}` | |||
| console.log(err) | |||
| reject(err) | |||
| } | |||
| resolve(tranRequest) | |||
| tranRequest.oncomplete = (event) => { | |||
| // console.log('beginReadonly 事务完毕:', window.performance.now()) | |||
| } | |||
| } | |||
| if (help._db) { | |||
| _tran() // 执行事务 | |||
| } else { | |||
| // 注册一个回调事件 | |||
| help._regCallback.push(() => _tran()) | |||
| } | |||
| }) | |||
| } | |||
| export default beginTran | |||
| @@ -0,0 +1,266 @@ | |||
| // 加载操作函数 | |||
| // 对象仓库的操作 | |||
| import _clearStore from './store-clear.js' // 清空仓库里的全部对象 | |||
| // model 的添加、修改、设置、获取、删除 | |||
| import _addModel from './model-add.js' // 添加一个对象 | |||
| import _putModel from './model-put.js' // 修改一个对象 | |||
| import _setModel from './model-set.js' // 修改一个对象 | |||
| import _getModel from './model-get.js' // 获取一个对象,或者全部(不能查询) | |||
| import _delModel from './model-delete.js' // 删除一个对象 | |||
| import _getCount from './model-count.js' // 获取仓库里的数量 | |||
| // 对象的查询 | |||
| import _listAll from './list-index.js' // 获取仓库里符合条件的对象,可以查询。 | |||
| import _listPager from './list-pager.js' // 分页获取对象,可以查询 | |||
| // 初始化和事务 | |||
| import _beginInit from './begin-init.js' // 初始化时用的事务 | |||
| import _beginTran from './begin-tran.js' // 事务 | |||
| /** | |||
| * indexedDB 的 help,基础功能的封装 | |||
| * * 打开数据库,建立对象仓库,获取连接对象,实现增删改查 | |||
| * * info 的结构: | |||
| * * * dbFlag: '' // 数据库标识,区别不同的数据库 | |||
| * * * dbConfig: { // 连接数据库 | |||
| * * * * dbName: '数据库名称', | |||
| * * * * ver: '数据库版本', | |||
| * * * }, | |||
| * * * stores: { | |||
| * * * * storeName: { // 对象仓库名称 | |||
| * * * * * id: 'id', // 主键名称 | |||
| * * * * * index: { // 可以不设置索引 | |||
| * * * * * * name: ture, // key:索引名称;value:是否可以重复 | |||
| * * * * * } | |||
| * * * * } | |||
| * * * }, | |||
| * * * init: (help) => {} // 完全准备好之后的回调函数 | |||
| */ | |||
| export default class IndexedDBHelp { | |||
| constructor (info) { | |||
| this.myIndexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB | |||
| if (!this.myIndexedDB) { | |||
| console.log('您的浏览器不支持 IndexedDB') | |||
| return | |||
| } | |||
| // 数据库名称和版本号 | |||
| this._info = { | |||
| dbName: info.dbConfig.dbName, | |||
| ver: info.dbConfig.ver | |||
| } | |||
| // 记录连接数据库的对象, IDBDatabase 类型,因为open是异步操作,所以不能立即获得。 | |||
| this._db = null | |||
| // 记录仓库状态。new:新库或者版本升级后;old:有对象仓库了。 | |||
| this._storeState = 'pending' | |||
| /** | |||
| * 注册回调事件。 | |||
| * * 如果组件读写 indexedDB 的时还没有准备好的话, | |||
| * * 可以来注册一个事件,等准备好了之后回调。 | |||
| */ | |||
| this._regCallback = [] | |||
| // 打开数据库,异步操作,大概需要几毫秒的时间。 | |||
| this.dbRequest = this.myIndexedDB.open(this._info.dbName, this._info.ver) | |||
| // 第一次,或者版本升级时执行,根据配置信息建立表 | |||
| this.dbRequest.onupgradeneeded = (event) => { | |||
| this._storeState = 'new' | |||
| const db = event.target.result | |||
| for (const key in info.stores) { | |||
| const store = info.stores[key] | |||
| if (db.objectStoreNames.contains(key)) { | |||
| // 已经有仓库,验证一下是否需要删除原来的仓库 | |||
| if (store.isClear) { | |||
| // 删除原对象仓库,没有保存数据 | |||
| db.deleteObjectStore(key) | |||
| // 建立新对象仓库 | |||
| const objectStore = db.createObjectStore(key, { keyPath: store.id }) | |||
| // 建立索引 | |||
| for (const key2 in store.index) { | |||
| const unique = store.index[key2] | |||
| objectStore.createIndex(key2, key2, { unique: unique }) | |||
| } | |||
| } | |||
| } else { | |||
| // 没有对象仓库,建立 | |||
| const objectStore = db.createObjectStore(key, { keyPath: store.id }) /* 自动创建主键 autoIncrement: true */ | |||
| // 建立索引 | |||
| for (const key2 in store.index) { | |||
| const unique = store.index[key2] | |||
| objectStore.createIndex(key2, key2, { unique: unique }) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // 数据库打开成功,记录连接对象 | |||
| this.dbRequest.onsuccess = async (event) => { | |||
| this._db = event.target.result // dbRequest.result | |||
| // console.log('【1】成功打开数据库 onsuccess --- ', this._db) | |||
| // 修改状态 | |||
| if (this._storeState === 'pending') { | |||
| this._storeState = 'old' | |||
| } | |||
| // 调用初始化的回调 | |||
| if (typeof info.init === 'function') { | |||
| await info.init(this) | |||
| } | |||
| // 调用组件注册的回调 | |||
| this._regCallback.forEach(fn => { | |||
| if (typeof fn === 'function') { | |||
| fn() | |||
| } | |||
| }) | |||
| } | |||
| // 处理出错信息 | |||
| this.dbRequest.onerror = (event) => { | |||
| // 出错 | |||
| console.log('打开数据库出错:', event.target.error) | |||
| } | |||
| } | |||
| // versionchange 全能事务 | |||
| // 初始化时批量添加对象的事务 | |||
| beginInit (storeName) { | |||
| return _beginInit(this, storeName) | |||
| } | |||
| // 读写的事务 | |||
| beginWrite (storeName) { | |||
| return _beginTran(this, storeName, 'readwrite') | |||
| } | |||
| // 只读的事务 | |||
| beginReadonly (storeName) { | |||
| return _beginTran(this, storeName, 'readonly') | |||
| } | |||
| /** | |||
| * 删掉整个库 | |||
| */ | |||
| deleteDB () { | |||
| // 定义一个 Promise 的实例 | |||
| const objectPromise = new Promise((resolve, reject) => { | |||
| // 删掉整个数据库 | |||
| const request = this.myIndexedDB.deleteDatabase(this._info.dbName) | |||
| request.onsuccess = (event) => { // 没有触发 | |||
| console.log('删掉整个数据库成功!', event) | |||
| resolve(event) | |||
| } | |||
| request.onblocked = (event) => { // 这个会被触发 | |||
| console.log('删除数据库的 blocked:', event) | |||
| // Close connections here | |||
| resolve(event) | |||
| } | |||
| request.onerror = (event) => { | |||
| console.log('删除数据库的 error:', event) | |||
| } | |||
| }) | |||
| return objectPromise | |||
| } | |||
| /** | |||
| * 清空一个对象仓库的全部对象 | |||
| * @param {string} storeName 对象仓库名称 | |||
| * @param {IDBTransaction} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| clearStore (storeName, tran = null) { | |||
| return _clearStore(this, storeName, tran) | |||
| } | |||
| /** | |||
| * 添加一个对象 | |||
| * @param {string} storeName 对象仓库名称 | |||
| * @param {object} model 要添加的对象 | |||
| * @param {IDBTransaction} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| addModel (storeName, model, tran = null) { | |||
| return _addModel(this, storeName, model, tran) | |||
| } | |||
| /** | |||
| * 修改一个对象 | |||
| * @param {string} storeName 对象仓库名称 | |||
| * @param {object} model 要修改的对象 | |||
| * @param {number} id 对象主键ID | |||
| * @param {IDBTransaction} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| putModel (storeName, model, id = null, tran = null) { | |||
| return _putModel(this, storeName, model, id, tran) | |||
| } | |||
| /** | |||
| * 添加或者修改一个对象 | |||
| * @param {string} storeName 对象仓库名称 | |||
| * @param {object} model 要添加或者修改的对象 | |||
| * @param {number} id 对象主键ID,判断有无的依据 | |||
| * @param {IDBTransaction} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| setModel (storeName, model, id = null, tran = null) { | |||
| return _setModel(this, storeName, model, id, tran) | |||
| } | |||
| /** | |||
| * 删除一个对象 | |||
| * @param {string} storeName 对象仓库名称 | |||
| * @param {object} id id 或者 model 要删除的对象 | |||
| * @param {IDBTransaction} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| delModel (storeName, id, tran = null) { | |||
| return _delModel(this, storeName, id, tran) | |||
| } | |||
| /** | |||
| * 获取一个对象,或者仓库的全部对象 | |||
| * @param {string} storeName 对象仓库名称 | |||
| * @param {number} id null:获取仓库的全部对象;其他:对象ID值 | |||
| * @param {IDBTransaction} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| getModel (storeName, id = null, tran = null) { | |||
| return _getModel(this, storeName, id, tran) | |||
| } | |||
| /** | |||
| * 获取对象仓库里全部对象的数量 | |||
| * @param {string} storeName 对象仓库名称 | |||
| * @param {IDBTransaction} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| getCount (storeName, tran = null) { | |||
| return _getCount(this, storeName, tran ) | |||
| } | |||
| /** | |||
| * 获取一个仓库的全部对象 | |||
| * @param {string} storeName 对象仓库名称 | |||
| * @param {object} query 查询条件 | |||
| * @param {IDBTransaction} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| getList (storeName, query = {}, tran = null) { | |||
| return _listAll(this, storeName, query, tran) | |||
| } | |||
| /** | |||
| * 获取一个仓库的全部对象 | |||
| * @param {string} storeName 对象仓库名称 | |||
| * @param {object} query 查询条件 | |||
| * @param {IDBTransaction} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| listPager (storeName, query = {}, tran = null) { | |||
| return _listPager(this, storeName, query, tran) | |||
| } | |||
| } | |||
| @@ -0,0 +1,149 @@ | |||
| import { reactive } from 'vue' | |||
| // 引入 indexedDB 的help | |||
| import IndexedDB from './help.js' | |||
| /** | |||
| * 对 indexedDB 的 help 进行初始化 | |||
| */ | |||
| export default { | |||
| _indexedDBFlag: Symbol('nf-indexedDB-help'), | |||
| _help: {}, // 访问数据库的实例 | |||
| _stores: {}, // 存放对象,实现 foo.addModel(obj)的功能 | |||
| /** | |||
| * 根据参数创建一个数据库的实例,初始化数据库 | |||
| * * 删表、建表、添加默认数据 | |||
| * @param {*} info 参数 | |||
| * @returns | |||
| * * dbFlag: '数据库标识,区分多个数据库', | |||
| * * dbConfig: { // 连接数据库 | |||
| * * * dbName: 'vite2-blog', | |||
| * * * ver: 1.0 | |||
| * * }, | |||
| * * init: () => {}, // 初始化完成后的回调函数 | |||
| * * stores: { | |||
| * * * storeName: { // 对象仓库名 | |||
| * * * * id: 'id', // 主键名称 | |||
| * * * * index: { | |||
| * * * * * name: ture, // 索引:是否可以重复 | |||
| * * * * }, | |||
| * * * * isDeleteOldTable: false, // 是否删除之前的对象仓库 | |||
| * * * } | |||
| * * } | |||
| */ | |||
| createHelp (info) { | |||
| const indexedDBFlag = typeof info.dbFlag === 'undefined' ? | |||
| this._indexedDBFlag : info.dbFlag | |||
| // 连接数据库,获得实例。 | |||
| const help = new IndexedDB(info) | |||
| const __stores = {} | |||
| // 存入静态对象,以便于支持保存多个不同的实例。 | |||
| this._help[indexedDBFlag] = help // help | |||
| this._stores[indexedDBFlag] = __stores // 仓库变对象 | |||
| help._stores = __stores // 挂到 help 上面 | |||
| // 把仓库变成对象的形式,避免写字符串的仓库名称 | |||
| for (const key in info.stores) { | |||
| __stores[key] = { | |||
| add: (obj, tran = null) => help.addModel(key, obj, tran), | |||
| get: (id = null, tran = null) => help.getModel(key, id, tran), | |||
| count: (tran = null) => help.getCount(key, tran), | |||
| put: (obj, tran = null) => { | |||
| let _id = obj | |||
| if (typeof obj === 'object') { | |||
| _id = obj[info.stores[key].id] | |||
| } | |||
| return help.putModel(key, obj, _id, tran) | |||
| }, | |||
| set: (obj, tran = null) => { | |||
| let _id = obj | |||
| if (typeof obj === 'object') { | |||
| _id = obj[info.stores[key].id] | |||
| } | |||
| return help.setModel(key, obj, _id, tran) | |||
| }, | |||
| del: (obj, tran = null) => { | |||
| let _id = obj | |||
| if (typeof obj === 'object') { | |||
| _id = obj[info.stores[key].id] | |||
| } | |||
| return help.delModel(key, _id, tran) | |||
| }, | |||
| list: (query = {}, tran = null) => help.getList(key, query, tran), | |||
| begin: () => help.beginWrite(key), | |||
| beginWrite: () => help.beginWrite(key), | |||
| beginReadonly: () => help.beginReadonly(key), | |||
| // 给model 加上增删改查的函数 | |||
| createModel: (model) => { | |||
| class MyModel { | |||
| constructor (_model) { | |||
| for (const key in _model) { | |||
| this[key] = _model[key] | |||
| } | |||
| } | |||
| /** | |||
| * 添加对象 | |||
| * @param {*} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| add(tran = null) { | |||
| return help.addModel(key, this, tran) | |||
| } | |||
| /** | |||
| * 保存对象,无则添加、有则修改 | |||
| * @param {*} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| save(tran = null) { | |||
| const _id = this[info.stores[key].id] | |||
| return help.setModel(key, this, _id, tran) | |||
| } | |||
| /** | |||
| * 加载对象,获取对象 | |||
| * @param {*} tran 事务,可以为 null | |||
| */ | |||
| load(tran = null) { | |||
| return new Promise((resolve, reject) => { | |||
| // 套个娃 | |||
| const _id = this[info.stores[key].id] | |||
| help.getModel(key, _id, tran).then((res) => { | |||
| Object.assign(this, res) | |||
| resolve(res) | |||
| }) | |||
| }) | |||
| } | |||
| /** | |||
| * 删除对象 | |||
| * @param {*} tran 事务,可以为 null | |||
| * @returns | |||
| */ | |||
| del(tran = null) { | |||
| const _id = this[info.stores[key].id] | |||
| return help.delModel(key, _id, tran) | |||
| } | |||
| } | |||
| const re = new MyModel(model) | |||
| return reactive(re) | |||
| } | |||
| } | |||
| } | |||
| return help | |||
| }, | |||
| // 获取静态对象里的数据库实例 | |||
| useDBHelp (_dbFlag) { | |||
| const flag = typeof _dbFlag === 'undefined' ? | |||
| this._indexedDBFlag : _dbFlag | |||
| return this._help[flag] | |||
| }, | |||
| useStores (_dbFlag) { | |||
| const flag = typeof _dbFlag === 'undefined' ? | |||
| this._indexedDBFlag : _dbFlag | |||
| return this._stores[flag] | |||
| } | |||
| } | |||
| @@ -0,0 +1,101 @@ | |||
| /** | |||
| * 不分页获取数据,可以查询 | |||
| * @param { dbHelp } help 访问数据库的实例 | |||
| * @param { Object } storeName 对象仓库 | |||
| * @param { Object } findInfo 查询条件 | |||
| * @param { Object } pager 排序字段 | |||
| * @returns 添加记录的ID | |||
| * * findInfo 结构(查询条件): | |||
| * * * { colName: [401, 11] } 字段名称,查询方式,查询关键字 | |||
| * * pager 结构: | |||
| * * * orderBy: { id: false } // 排序字段:字段名,false表示倒序。 | |||
| */ | |||
| const getList = (help, storeName, findInfo = {}, pager = {}) => { | |||
| const _start = page.start || 0 | |||
| const _count = page.count || 0 | |||
| const _end = _start + _count | |||
| const _description = pager.description || 'prev' // 默认倒序 | |||
| // 查询条件,按照主键或者索引查询 | |||
| let keyRange = null | |||
| if (typeof findInfo.indexName !== 'undefined') { | |||
| if (typeof findInfo.indexKind !== 'undefined') { | |||
| const id = findInfo.indexValue | |||
| const dicRange = { | |||
| '=': IDBKeyRange.only(id), | |||
| '>': IDBKeyRange.lowerBound(id, true), | |||
| '>=': IDBKeyRange.lowerBound(id), | |||
| '<': IDBKeyRange.upperBound(id, true), | |||
| '<=': IDBKeyRange.upperBound(id) | |||
| } | |||
| const betweenInfo = findInfo.betweenInfo | |||
| switch (findInfo.indexKind) { | |||
| case '=': | |||
| case '>': | |||
| case '>=': | |||
| case '<': | |||
| case '<=': | |||
| keyRange = dicRange[findInfo.indexKind] | |||
| break | |||
| case 'between': | |||
| keyRange = IDBKeyRange.bound(betweenInfo.v1, betweenInfo.v2, betweenInfo.v1isClose, betweenInfo.v2isClose) | |||
| break | |||
| } | |||
| } | |||
| } | |||
| console.log('findObject - keyRange', keyRange) | |||
| return new Promise((resolve, reject) => { | |||
| const _getList = (__tran) => { | |||
| const store = tranRequest.objectStore(storeName) | |||
| let cursorRequest | |||
| // 打开游标 | |||
| cursorRequest = store.openCursor(keyRange, _description) | |||
| // 使用游标查询对象并且返回 | |||
| cursorRequest.onsuccess = (event) => { | |||
| const cursor = event.target.result | |||
| if (cursor) { | |||
| if (_end === 0 || (cursorIndex >= _start && cursorIndex < _end)) { | |||
| // 判断钩子函数 | |||
| if (typeof findInfo.where === 'function') { | |||
| if (findInfo.where(cursor.value, cursorIndex)) { | |||
| dataList.push(cursor.value) | |||
| cursorIndex++ | |||
| } | |||
| } else { // 没有设置查询条件 | |||
| dataList.push(cursor.value) | |||
| cursorIndex++ | |||
| } | |||
| } | |||
| cursor.continue() | |||
| } | |||
| // tranRequest.commit() | |||
| } | |||
| tranRequest.oncomplete = (event) => { | |||
| if (config.debug) { | |||
| console.log('findObjectByIndex - dataList', dataList) | |||
| } | |||
| resolve(dataList) | |||
| } | |||
| tranRequest.onerror = (event) => { | |||
| console.log('findObjectByIndex - onerror', event) | |||
| reject(event) | |||
| } | |||
| } | |||
| // 判断数据库是否打开 | |||
| if (tranRequest === null) { | |||
| // 自己开一个事务 | |||
| help.beginReadonly([storeName]).then((tran) => { | |||
| _getList(tran) | |||
| tran.commit() // 可以快点提交事务,好吧其实也没快。 | |||
| }) | |||
| } else { | |||
| _getList(tranRequest) | |||
| } | |||
| }) | |||
| } | |||
| export default getList | |||
| @@ -0,0 +1,60 @@ | |||
| import _toIndex from './_toIndex.js' | |||
| /** | |||
| * 用索引查询数据 | |||
| * @param { IndexedDBHelp } help 访问数据库的实例 | |||
| * @param { string } storeName 仓库名称(表名) | |||
| * @param { Object } query 查询条件 | |||
| * * query: { | |||
| * * * keyName1: [401, xxx], // 第一个是索引, | |||
| * * * keyName2: [402, xxx] // 后面的不算索引 | |||
| * * } | |||
| * @param { IDBTransaction } tranRequest 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 要获取的对象 | |||
| */ | |||
| const getList = (help, storeName, query = {}, tranRequest = null) => { | |||
| return new Promise((resolve, reject) => { | |||
| // 定义个函数,便于调用 | |||
| const _getList = (__tran) => { | |||
| const store = __tran.objectStore(storeName) | |||
| // 分析查询条件,设置索引和其他条件 | |||
| const { range, other, find } = _toIndex(store.indexNames, query) | |||
| const keys = Object.keys(query) | |||
| // 设置索引的查询条件 | |||
| // 打开对象仓库或者索引 ? 不用索引,直接用对象仓库 : 使用索引 | |||
| const dbRequest = range === null ? store : store.index(keys[0]) | |||
| // // 直接开游标 : // 带条件的开游标 | |||
| const cursor = range === null ? dbRequest.openCursor() : dbRequest.openCursor(range) | |||
| const arr = [] // 返回的记录集 | |||
| let i = 0 | |||
| cursor.onsuccess = (event) => { // 打开成功 | |||
| const res = event.target.result | |||
| console.log('游标:' + i++, res) | |||
| if (res) { | |||
| // 判断其他查询条件 | |||
| if (find(other, res.value)) { | |||
| arr.push(res.value) | |||
| } | |||
| res.continue() // 继续下一个 | |||
| } else { | |||
| // 没有了 | |||
| resolve(arr) // 返回对象 | |||
| } | |||
| } | |||
| } | |||
| // 判断数据库是否打开 | |||
| if (tranRequest === null) { | |||
| // 自己开一个事务 | |||
| help.beginReadonly([storeName]).then((tran) => { | |||
| _getList(tran) | |||
| // tran.commit() // 可以快点提交事务,好吧其实也没快。 | |||
| }) | |||
| } else { | |||
| _getList(tranRequest) | |||
| } | |||
| }) | |||
| } | |||
| export default getList | |||
| @@ -0,0 +1,120 @@ | |||
| /** | |||
| * 获取分页列表数据 | |||
| * @param { IndexedDBHelp } help 访问数据库的实例 | |||
| * @param { string } storeName 仓库名称(表名) | |||
| * @param { Object } model 对象(数据记录) | |||
| * @param { IDBTransaction } tranRequest 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * storeName: '', 对象仓库名 | |||
| * * info 结构: | |||
| * * * find: { | |||
| * * * * indexName: 'groupId', | |||
| * * * * indexKind: '=', // '>','>=','<','<=','between', | |||
| * * * }, | |||
| * * * pager: { | |||
| * * * * start:开始, | |||
| * * * * count:数量, | |||
| * * * * description:'next' | |||
| * * * * indexValue: 1, | |||
| * * * * betweenInfo: { | |||
| * * * * * v1:1, | |||
| * * * * * v2:2, | |||
| * * * * * v1isClose:true, | |||
| * * * * * v2isClose:true, | |||
| * * * * }, | |||
| * * * * where:(object) => { | |||
| * * * * * reutrn true/false | |||
| * * * * } | |||
| * * * } | |||
| */ | |||
| export default function pager (help, storeName, info, tranRequest = null) { | |||
| const _start = info.pager.start || 0 | |||
| const _count = info.pager.count || 0 | |||
| const _end = _start + _count | |||
| const _description = info.pager.description || 'prev' // 默认倒序 | |||
| // 查询条件,按照主键或者索引查询 | |||
| let keyRange = null | |||
| if (typeof info.find.indexName !== 'undefined') { | |||
| if (typeof info.find.indexKind !== 'undefined') { | |||
| const id = info.find.indexValue | |||
| const dicRange = { | |||
| '=': IDBKeyRange.only(id), | |||
| '>': IDBKeyRange.lowerBound(id, true), | |||
| '>=': IDBKeyRange.lowerBound(id), | |||
| '<': IDBKeyRange.upperBound(id, true), | |||
| '<=': IDBKeyRange.upperBound(id) | |||
| } | |||
| const betweenInfo = info.find.betweenInfo || '==' | |||
| switch (findInfo.indexKind) { | |||
| case '=': | |||
| case '>': | |||
| case '>=': | |||
| case '<': | |||
| case '<=': | |||
| keyRange = dicRange[findInfo.indexKind] | |||
| break | |||
| case 'between': | |||
| keyRange = IDBKeyRange.bound(betweenInfo.v1, betweenInfo.v2, betweenInfo.v1isClose, betweenInfo.v2isClose) | |||
| break | |||
| } | |||
| } | |||
| } | |||
| console.log('pager - keyRange', keyRange) | |||
| // 定义一个 Promise 的实例 | |||
| return new Promise((resolve, reject) => { | |||
| const dataList = [] | |||
| // 定义个函数,便于调用 | |||
| const _pager = (__tran) => { | |||
| let cursorIndex = 0 | |||
| const store = __tran.objectStore(storeName) | |||
| let cursorRequest | |||
| // 判断是否索引查询 | |||
| if (typeof findInfo.indexName === 'undefined') { | |||
| cursorRequest = store.openCursor(keyRange, _description) | |||
| } else { | |||
| cursorRequest = store | |||
| .index(info.find.indexName) | |||
| .openCursor(keyRange, _description) | |||
| } | |||
| cursorRequest.onsuccess = (event) => { | |||
| const cursor = event.target.result | |||
| if (cursor) { | |||
| if (_end === 0 || (cursorIndex >= _start && cursorIndex < _end)) { | |||
| // 判断钩子函数 | |||
| if (typeof findInfo.where === 'function') { | |||
| if (findInfo.where(cursor.value, cursorIndex)) { | |||
| dataList.push(cursor.value) | |||
| cursorIndex++ | |||
| } | |||
| } else { // 没有设置查询条件 | |||
| dataList.push(cursor.value) | |||
| cursorIndex++ | |||
| } | |||
| } | |||
| cursor.continue() | |||
| } | |||
| // __tran.commit() | |||
| } | |||
| __tran.oncomplete = (event) => { | |||
| if (config.debug) { | |||
| console.log('oncomplete - pager - dataList', dataList) | |||
| } | |||
| resolve(dataList) | |||
| } | |||
| } | |||
| if (tranRequest === null) { | |||
| help.beginReadonly([storeName]).then((tran) => { | |||
| // 自己开一个事务 | |||
| _pager(tran) | |||
| }) | |||
| } else { | |||
| // 使用传递过来的事务 | |||
| _pager(tranRequest) | |||
| } | |||
| }) | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| import _vueToObject from './_toObject.js' | |||
| /** | |||
| * 添加对象 | |||
| * @param { IndexedDBHelp } help 访问数据库的实例 | |||
| * @param { string } storeName 仓库名称(表名) | |||
| * @param { Object } model 对象(数据记录) | |||
| * @param { IDBTransaction } tranRequest 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 新对象的ID | |||
| */ | |||
| export default function addModel (help, storeName, model, tranRequest = null) { | |||
| console.log('添加对象的 this', this) | |||
| // 取对象的原型,便于保存 reactive | |||
| const _model = _vueToObject(model) | |||
| // 定义一个 Promise 的实例 | |||
| return new Promise((resolve, reject) => { | |||
| // 定义个函数,便于调用 | |||
| const _add = (__tran) => { | |||
| __tran | |||
| .objectStore(storeName) // 获取store | |||
| .add(_model) // 添加对象 | |||
| .onsuccess = (event) => { // 成功后的回调 | |||
| resolve(event.target.result) // 返回对象的ID | |||
| } | |||
| } | |||
| if (tranRequest === null) { | |||
| help.beginWrite([storeName]).then((tran) => { | |||
| // 自己开一个事务 | |||
| _add(tran) | |||
| }) | |||
| } else { | |||
| // 使用传递过来的事务 | |||
| _add(tranRequest) | |||
| } | |||
| }) | |||
| } | |||
| @@ -0,0 +1,35 @@ | |||
| /** | |||
| * 获取对象 | |||
| * @param { IndexedDBHelp } help 访问数据库的实例 | |||
| * @param { string } storeName 仓库名称(表名) | |||
| * @param { IDBTransaction } tran 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 要获取的对象 | |||
| */ | |||
| export default function getCount (help, storeName, tran = null) { | |||
| return new Promise((resolve, reject) => { | |||
| // 定义个函数,便于调用 | |||
| const _getCount = (__tran) => { | |||
| const store = __tran.objectStore(storeName) | |||
| // console.log('对象仓库--', store) | |||
| // 判断是获取一个,还是获取全部 | |||
| const dbRequest = store.count() | |||
| // console.log('dbRequest--', dbRequest) | |||
| dbRequest.onsuccess = (event) => { // 成功后的回调 | |||
| // console.log('-- 得到数据 --:', window.performance.now()) | |||
| resolve(event.target.result) // 返回对象 | |||
| } | |||
| } | |||
| // 判断数据库是否打开 | |||
| if (tran === null) { | |||
| // 自己开一个事务 | |||
| help.beginReadonly([storeName]).then((tran) => { | |||
| _getCount(tran) | |||
| tran.commit() // 可以快点提交事务,好吧其实也没快。 | |||
| }) | |||
| } else { | |||
| _getCount(tran) | |||
| } | |||
| }) | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| /** | |||
| * 删除对象 | |||
| * @param { IndexedDBHelp } help 访问数据库的实例 | |||
| * @param { string } storeName 仓库名称(表名) | |||
| * @param { string } id 对象的ID | |||
| * @param { IDBTransaction } tranRequest 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * idKey: 'id', 主键字段名称 | |||
| */ | |||
| export default function deleteData (help, storeName, id, tranRequest = null) { | |||
| // 定义一个 Promise 的实例 | |||
| return new Promise((resolve, reject) => { | |||
| // 定义个函数,便于调用 | |||
| const _delete = (__tran) => { | |||
| __tran | |||
| .objectStore(storeName) // 获取store | |||
| .delete(id) // 删除一个对象 | |||
| .onsuccess = (event) => { // 成功后的回调 | |||
| resolve(event.target.result) | |||
| } | |||
| } | |||
| // 判断是否有事务 | |||
| if (tranRequest === null) { | |||
| help.beginWrite([storeName]).then((tran) => { | |||
| _delete(tran) | |||
| }) | |||
| } else { | |||
| _delete(tranRequest) | |||
| } | |||
| }) | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| /** | |||
| * 获取对象 | |||
| * @param { IndexedDBHelp } help 访问数据库的实例 | |||
| * @param { string } storeName 仓库名称(表名) | |||
| * @param { Object } id 对象(提供id) | |||
| * @param { IDBTransaction } tranRequest 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 要获取的对象 | |||
| */ | |||
| export default function getModel (help, storeName, id = null, tranRequest = null) { | |||
| return new Promise((resolve, reject) => { | |||
| // 定义个函数,便于调用 | |||
| const _getModel = (__tran) => { | |||
| const store = __tran.objectStore(storeName) | |||
| // console.log('对象仓库--', store) | |||
| // 判断是获取一个,还是获取全部 | |||
| const dbRequest = id === null ? store.getAll() : store.get(id) | |||
| // console.log('dbRequest--', dbRequest) | |||
| dbRequest.onsuccess = (event) => { // 成功后的回调 | |||
| // console.log('-- 得到数据 --:', window.performance.now()) | |||
| resolve(event.target.result) // 返回对象 | |||
| } | |||
| } | |||
| // 判断数据库是否打开 | |||
| if (tranRequest === null) { | |||
| // 自己开一个事务 | |||
| help.beginReadonly([storeName]).then((tran) => { | |||
| _getModel(tran) | |||
| tran.commit() // 可以快点提交事务,好吧其实也没快。 | |||
| }) | |||
| } else { | |||
| _getModel(tranRequest) | |||
| } | |||
| }) | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| import _vueToObject from './_toObject.js' | |||
| /** | |||
| * 修改对象,先依据ID获取对象,然后把model的属性叠加上去,最后put新对象 | |||
| * @param { IndexedDBHelp } help 访问数据库的实例 | |||
| * @param { string } storeName 仓库名称(表名) | |||
| * @param { Object } model 对象(数据记录) | |||
| * @param { string } id 对象的ID | |||
| * @param { IDBTransaction } tranRequest 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| */ | |||
| export default function updateData (help, storeName, model, id, tranRequest = null) { | |||
| const _model = _vueToObject(model) | |||
| // 定义一个 Promise 的实例 | |||
| return new Promise((resolve, reject) => { | |||
| // 定义个函数,便于调用 | |||
| const _update = (__tran) => { | |||
| // 先获取对象,然后修改对象,最后存回去 | |||
| const store = __tran.objectStore(storeName) // 获取store | |||
| store.get(id) // 获取对象 | |||
| .onsuccess = (event) => { // 成功后的回调 | |||
| // 从仓库里提取对象,把修改值合并到对象里面。 | |||
| const newObject = {} | |||
| Object.assign(newObject, event.target.result, _model) | |||
| // 修改数据 | |||
| store.put(newObject) // 修改对象 | |||
| .onsuccess = (event) => { // 成功后的回调 | |||
| resolve(event.target.result) | |||
| } | |||
| } | |||
| } | |||
| // 判断是否自带事务 | |||
| if (tranRequest === null) { | |||
| help.beginWrite([storeName]).then((tran) => { | |||
| // 自己开一个事务 | |||
| _update(tran) | |||
| }) | |||
| } else { | |||
| // 使用传递过来的事务 | |||
| _update(tranRequest) | |||
| } | |||
| }) | |||
| } | |||
| @@ -0,0 +1,53 @@ | |||
| import _vueToObject from './_toObject.js' | |||
| /** | |||
| * 添加或者修改对象,先依据ID判断是否有对象,无则添,有则改 | |||
| * @param { IndexedDBHelp } help 访问数据库的实例 | |||
| * @param { string } storeName 仓库名称(表名) | |||
| * @param { Object } model 对象(数据记录) | |||
| * @param { string } id 对象的ID | |||
| * @param { IDBTransaction } tranRequest 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| */ | |||
| export default function setData (help, storeName, model, id, tranRequest = null) { | |||
| const _model = _vueToObject(model) | |||
| // 定义一个 Promise 的实例 | |||
| return new Promise((resolve, reject) => { | |||
| // 定义个函数,便于调用 | |||
| const _set = (__tran) => { | |||
| // 先获取对象,然后修改对象,最后存回去 | |||
| const store = __tran.objectStore(storeName) // 获取store | |||
| store.get(id) // 获取对象 | |||
| .onsuccess = (event) => { // 成功后的回调 | |||
| // 从仓库里提取对象,把修改值合并到对象里面。 | |||
| const res = event.target.result | |||
| if (typeof res === 'undefined') { | |||
| // 没有对象添加 | |||
| store.add(_model) // 添加对象 | |||
| .onsuccess = (event) => { // 成功后的回调 | |||
| resolve(event.target.result) // 返回对象的ID | |||
| } | |||
| } else { | |||
| // 修改 | |||
| const newObject = {} | |||
| Object.assign(newObject, event.target.result, _model) | |||
| // 修改数据 | |||
| store.put(newObject) // 修改对象 | |||
| .onsuccess = (event) => { // 成功后的回调 | |||
| resolve(event.target.result) | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // 判断是否自带事务 | |||
| if (tranRequest === null) { | |||
| help.beginWrite([storeName]).then((tran) => { | |||
| // 自己开一个事务 | |||
| _set(tran) | |||
| }) | |||
| } else { | |||
| // 使用传递过来的事务 | |||
| _set(tranRequest) | |||
| } | |||
| }) | |||
| } | |||
| @@ -0,0 +1,30 @@ | |||
| /** | |||
| * 清空仓库 store 里的对象 | |||
| * @param { IndexedDBHelp } help 访问数据库的实例 | |||
| * @param { string } storeName 仓库名称(表名) | |||
| * @param { IDBTransaction } tranRequest 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns | |||
| */ | |||
| export default function deleteStore (help, storeName, tranRequest = null) { | |||
| // 定义一个 Promise 的实例 | |||
| return new Promise((resolve, reject) => { | |||
| // 定义个函数,便于调用 | |||
| const _clearStore = (__tran) => { | |||
| __tran | |||
| .objectStore(storeName) // 获取store | |||
| .clear() // 删除store | |||
| .onsuccess = (event) => { // 成功后的回调 | |||
| resolve(event) // 返回对象的ID | |||
| } | |||
| } | |||
| if (tranRequest === null) { | |||
| help.beginWrite([storeName]).then((tran) => { | |||
| // 自己开一个事务 | |||
| _clearStore(tran) | |||
| }) | |||
| } else { | |||
| // 使用传递过来的事务 | |||
| _clearStore(tranRequest) | |||
| } | |||
| }) | |||
| } | |||
| @@ -0,0 +1,34 @@ | |||
| /** | |||
| * 内部函数,根据分页信息,设置 分页信息和排序字段 | |||
| * @param { object } pager 分页和排序 | |||
| * @returns order by 和 limit | |||
| */ | |||
| const _getPager = (pager) => { | |||
| const re = { | |||
| orderBy: '', // 分页,可以不设置 | |||
| limit: '' // 排序,可以不设置 | |||
| } | |||
| // 设置分页 order by 和 limit | |||
| if (typeof pager !== 'undefined') { | |||
| if (typeof pager.pagerIndex !== 'undefined') { | |||
| // 用 limit 实现分页 | |||
| const _pageSize = pager.pagerSize || 10 | |||
| const index = _pageSize * (pager.pagerIndex - 1) | |||
| re.limit = ` limit ${index}, ${_pageSize} ` | |||
| } | |||
| if (typeof pager.orderBy === 'object') { | |||
| // 设置排序字段和方式 | |||
| const arr = [] | |||
| for (const key in pager.orderBy) { | |||
| const col = key | |||
| const isAsc = pager.orderBy[key] ? ' asc ' : ' desc ' | |||
| arr.push(col + ' ' + isAsc) | |||
| } | |||
| re.orderBy = ` order by ${arr.join(',')}` | |||
| } | |||
| } | |||
| return re | |||
| } | |||
| export default _getPager | |||
| @@ -0,0 +1,82 @@ | |||
| /** | |||
| * 内部函数,根据查询条件,拼接查询用的SQL语句,where 后面的部分。 | |||
| * @param {object} query 查询条件 | |||
| * @returns where 后面的查询语句 | |||
| */ | |||
| const _getWhereQuery = (query) => { | |||
| // 查询条件 | |||
| const findKind = { | |||
| // 字符串 | |||
| 401: ' {col} = ? ', | |||
| 402: ' {col} <> ? ', | |||
| 403: ' {col} like ? ', | |||
| 404: ' {col} not like ? ', | |||
| 405: ' {col} like ? ', // 起始于 | |||
| 406: ' {col} like ? ', // 结束于 | |||
| // 数字 | |||
| 411: ' {col} = ? ', | |||
| 412: ' {col} <> ? ', | |||
| 413: ' {col} > ? ', | |||
| 414: ' {col} >= ? ', | |||
| 415: ' {col} < ? ', | |||
| 416: ' {col} <= ? ', | |||
| 417: ' {col} between ? and ? ', | |||
| // 日期 | |||
| 421: ' {col} = ? ', | |||
| 422: ' {col} <> ? ', | |||
| 423: ' {col} > ? ', | |||
| 424: ' {col} >= ? ', | |||
| 425: ' {col} < ? ', | |||
| 426: ' {col} <= ? ', | |||
| 427: ' {col} between ? and ? ', | |||
| // 范围 | |||
| 441: ' {col} in (?)' | |||
| } | |||
| const _whereCol = [] // 查询字段 | |||
| const _whereValue = [] // 查询参数 | |||
| // 设置查询条件 | |||
| for (const key in query) { | |||
| const val = query[key] | |||
| if (val[1] === '' || val[1] === null) continue | |||
| _whereCol.push(findKind[val[0]].replace('{col}', key)) | |||
| switch (val[0]) { | |||
| case 403: // like | |||
| case 404: // not like | |||
| _whereValue.push('%' + val[1] + '%') | |||
| break | |||
| case 405: // like a% | |||
| _whereValue.push(val[1] + '%') | |||
| break | |||
| case 406: // like %a | |||
| _whereValue.push('%' + val[1]) | |||
| break | |||
| case 417: // between 数字 | |||
| case 427: // between 日期 | |||
| _whereValue.push(...val[1]) | |||
| break | |||
| case 441: // in | |||
| _whereCol[_whereCol.length - 1] = | |||
| _whereCol[_whereCol.length - 1] | |||
| .replace('?', val[1].map(a => '?').join(',')) | |||
| _whereValue.push(...val[1]) | |||
| break | |||
| default: | |||
| _whereValue.push(val[1]) | |||
| break | |||
| } | |||
| } | |||
| const re = { | |||
| whereQuery: '', | |||
| whereValue: [] | |||
| } | |||
| // 如果没有查询添加,设置 1=1 占位 | |||
| if (_whereCol.length > 0) { | |||
| re.whereQuery = ` WHERE ${_whereCol.join(' and ')}`, | |||
| re.whereValue = _whereValue | |||
| } | |||
| return re | |||
| } | |||
| export default _getWhereQuery | |||
| @@ -0,0 +1,53 @@ | |||
| /** | |||
| * 实现添加数据的功能。拼接 insert 的 SQL语句 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { Object } meta 表、字段 | |||
| * @param { Object } model 数据 | |||
| * @param { connection } cn 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * cols: { colName: '', ...} | |||
| * * model 结构: | |||
| * * * colName: value | |||
| */ | |||
| export default function addData (help, meta, model, cn = null) { | |||
| // 拼接添加用的SQL语句, | |||
| // 提交SQL语句 | |||
| // console.log('addData,开始运行 :') | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| // 记录字段名称 | |||
| const colNames = [] | |||
| // 记录字段对应的值 | |||
| const colValues = [] | |||
| // 记录字段对应的占位符合 | |||
| const cols = [] | |||
| // 变量对象,记录 key和 value | |||
| const colKeys = meta.cols || model | |||
| for (const key in colKeys) { | |||
| if (key.toLocaleLowerCase() === 'id') continue | |||
| colNames.push(key) | |||
| // 判断类型 | |||
| if (typeof model[key] === 'object') { | |||
| colValues.push(JSON.stringify(model[key])) | |||
| } else { | |||
| colValues.push(model[key]) | |||
| } | |||
| cols.push('?') | |||
| } | |||
| const sql = `INSERT INTO ${meta.tableName} ( ${colNames.join(',')} ) VALUES ( ${cols.join(',')} )` | |||
| // console.log('insertSQL:', sql) | |||
| help.query(sql, colValues, cn) | |||
| .then((res) => { | |||
| // 成功了,返回给调用者 | |||
| resolve(res.insertId) | |||
| }) | |||
| .catch((err) => { | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| /** | |||
| * 实现删除数据的功能。物理删除,delete from | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { Object } meta 表、字段 | |||
| * @param { number|string } id 主键字段值 | |||
| * @param { connection } cn 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * idKey: 'id', 主键字段名称 | |||
| */ | |||
| export default function deleteData (help, meta, id, cn = null) { | |||
| // 拼接添加用的SQL语句, | |||
| // 提交SQL语句 | |||
| // console.log('deleteData,开始运行 :') | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| const sql = `DELETE FROM ${meta.tableName} WHERE ${meta.idKey}=?` | |||
| console.log('sql-----delete:', sql, id) | |||
| help.query(sql, [id], cn) | |||
| .then((res) => { | |||
| // 成功了,返回给调用者 | |||
| resolve(res.rowsAffected) | |||
| }) | |||
| .catch((err) => { | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| /** | |||
| * 实现删除数据的功能。逻辑删除,update set flag = 1 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { Object } meta 表、字段 | |||
| * @param { number|string } id 主键字段值 | |||
| * @param { connection } cn 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * idKey: 'id', 主键字段名称 | |||
| * * * delFlag: 'isDel', 逻辑删除,标记字段名称 | |||
| */ | |||
| export default function deleteData (help, meta, id, cn = null) { | |||
| // 拼接添加用的SQL语句, | |||
| // 提交SQL语句 | |||
| // console.log('deleteData,开始运行 :') | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| const sql = `UPDATE ${meta.tableName} SET ${meta.delFlag} = 1 WHERE ${meta.idKey}=?` | |||
| // console.log('sql:', sql) | |||
| help.query(sql, [id], cn) | |||
| .then((res) => { | |||
| // 成功了,返回给调用者 | |||
| resolve(res.rowsAffected) | |||
| }) | |||
| .catch((err) => { | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| /** | |||
| * 依据主键字段,获取记录 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { Object } meta 表、字段 | |||
| * @param { number|string } id 主键字段值 | |||
| * @param { connection } cn 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * idKey: 'id', 主键字段名称 | |||
| */ | |||
| export default function getData (help, meta, id, cn = null) { | |||
| // 拼接添加用的SQL语句, | |||
| // 提交SQL语句 | |||
| // console.log('getData,开始运行 :') | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| const sql = `SELECT * FROM ${meta.tableName} WHERE ${meta.idKey || 'id'}=?` | |||
| // console.log('SELECT -- sql:', sql, id) | |||
| help.query(sql, [id], cn) | |||
| .then((res) => { | |||
| // 成功了,返回给调用者 | |||
| resolve(res.rows) | |||
| }) | |||
| .catch((err) => { | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,54 @@ | |||
| import add from './data-add' | |||
| import update from './data-update' | |||
| /** | |||
| * 实现添加/修改数据的功能。没有ID:添加,有ID:修改 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { Object } meta 表、字段 | |||
| * @param { Object } model 数据 | |||
| * @param { number|string } id 主键字段值 | |||
| * @param { connection } cn 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 影响的行数 | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * idKey: 'id', 主键字段名称 | |||
| * * model 结构: | |||
| * * * colName: value | |||
| */ | |||
| export default function updateData (help, meta, model, id, cn = null) { | |||
| // 拼接修改用的SQL语句, | |||
| // console.log('updateData,开始运行 :') | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| // 记录字段名称 | |||
| const colNames = [] | |||
| // 记录字段对应的值 | |||
| const colValues = [] | |||
| // 变量对象,记录 key和 value | |||
| const colKeys = meta.cols || model | |||
| for (const key in colKeys) { | |||
| colNames.push(key + '=? ') | |||
| if (typeof model[key] === 'object') { | |||
| colValues.push(JSON.stringify(model[key], null, 2)) | |||
| } else { | |||
| colValues.push(model[key]) | |||
| } | |||
| } | |||
| // 加入查询条件 | |||
| colValues.push(id) | |||
| const sql = `SELECT 1 FROM ${meta.tableName} WHERE ${meta.idKey || 'id'}=?` | |||
| // console.log('updateSQL:', sql) | |||
| help.query(sql, colValues, cn).then((res) => { | |||
| add(help, meta, model, id, cn).then((res1) => { | |||
| // 成功了,返回给调用者 | |||
| resolve(res.rowsAffected) | |||
| }) | |||
| }).catch((err) => { | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,50 @@ | |||
| /** | |||
| * 实现修改数据的功能。拼接 update 的 SQL语句 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { Object } meta 表、字段 | |||
| * @param { Object } model 数据 | |||
| * @param { number|string } id 主键字段值 | |||
| * @param { connection } cn 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 影响的行数 | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * idKey: 'id', 主键字段名称 | |||
| * * model 结构: | |||
| * * * colName: value | |||
| */ | |||
| export default function updateData (help, meta, model, id, cn = null) { | |||
| // 拼接修改用的SQL语句, | |||
| // console.log('updateData,开始运行 :') | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| // 记录字段名称 | |||
| const colNames = [] | |||
| // 记录字段对应的值 | |||
| const colValues = [] | |||
| // 变量对象,记录 key和 value | |||
| const colKeys = meta.cols || model | |||
| for (const key in colKeys) { | |||
| colNames.push(key + '=? ') | |||
| if (typeof model[key] === 'object') { | |||
| colValues.push(JSON.stringify(model[key], null, 2)) | |||
| } else { | |||
| colValues.push(model[key]) | |||
| } | |||
| } | |||
| // 加入查询条件 | |||
| colValues.push(id) | |||
| const sql = `UPDATE ${meta.tableName} SET ${colNames.join(',')} WHERE ${meta.idKey}=?` | |||
| // console.log('updateSQL:', sql) | |||
| help.query(sql, colValues, cn) | |||
| .then((res) => { | |||
| // 成功了,返回给调用者 | |||
| resolve(res.rowsAffected) | |||
| }) | |||
| .catch((err) => { | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,28 @@ | |||
| /** | |||
| * 删除数据库 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { string } dbName 数据库名称 | |||
| * @param { connection } cn 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * idKey: 'id', 主键字段名称 | |||
| * * * delFlag: 'isDel', 逻辑删除,标记字段名称 | |||
| */ | |||
| export default function deleteTable (help, dbName, cn = null) { | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| const sql = `DROP database ${dbName} ` | |||
| // console.log('sql:', sql) | |||
| help.query(sql, [], cn) | |||
| .then((res) => { | |||
| // 成功了,返回给调用者 | |||
| resolve(res) | |||
| }) | |||
| .catch((err) => { | |||
| console.log('deleteDataBase-sql:', sql, err) | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,203 @@ | |||
| import _addModel from './data-add.js' // 添加一个对象 | |||
| import _updateModel from './data-update.js' // 修改一个对象 | |||
| import _getModel from './data-get.js' // 获取一个对象 | |||
| import _deleteModel from './data-delete.js' // 删除一个对象 | |||
| import _listAll from './list-all.js' // 获取仓库里全部对象 | |||
| import _listCount from './list-count.js' // 统计对象数量 | |||
| import _listPager from './list-pager.js' // 分页获取对象 | |||
| /** | |||
| * 基于 promise 封装 webSQL 的基本操作 | |||
| * * 创建数据库连接 | |||
| * * 提交SQL给数据库执行,得到返回结果 | |||
| * * 共用函数 | |||
| * * info 结构: | |||
| * * * dbName: 'test', // 数据库名称 | |||
| * * * ver: '1', // 版本,很重要 | |||
| * * * size: '2', // 大小,自动 * 1024 * 1024 | |||
| * * * description: '数据库描述' | |||
| */ | |||
| export default class MySQLHelp { | |||
| constructor (info) { | |||
| if (!window.openDatabase) { | |||
| console.log('您的浏览器不支持 webSQL') | |||
| return | |||
| } | |||
| // 数据库连接信息 | |||
| this._info = { | |||
| dbName: info.dbName, | |||
| ver: info.ver, | |||
| size: info.size, | |||
| description: info.infodescription | |||
| } | |||
| // 打开数据库 | |||
| this.db = window.openDatabase( | |||
| this._info.dbName, | |||
| this._info.ver, | |||
| this._info.description, | |||
| this._info.size * 1024 * 1024) | |||
| // console.log('\n db', this.db.version) | |||
| } | |||
| /** | |||
| * 运行 SQL 语句,带参数,返回执行结果 | |||
| * @param { string } sql SQL语句 | |||
| * @param { array } param 参数 | |||
| * @param { object } tran 参数 | |||
| * @returns promise | |||
| */ | |||
| query (sql, param = [], tran = null) { | |||
| const promise1 = new Promise((resolve, reject) => { | |||
| const _query = (tran) => { | |||
| tran.executeSql(sql, param, | |||
| (tx, results) => { resolve(results) }, | |||
| (tx, err) => { | |||
| console.log('query - sql:', sql, param, tx, err) | |||
| reject(err) | |||
| return true // 回滚 | |||
| } | |||
| ) | |||
| } | |||
| if (tran === null) { | |||
| this.begin().then((_tran) => { | |||
| _query(_tran) | |||
| }) | |||
| } else { | |||
| _query(tran) | |||
| } | |||
| }) | |||
| return promise1 | |||
| } | |||
| /** | |||
| * 开启一个事务,Promise 的方式 | |||
| * @returns Promise 形式 | |||
| */ | |||
| begin () { | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| // 开启一个事务。 | |||
| // console.log('★ 开启事务,promise 模式') | |||
| this.db.transaction( | |||
| (tran) => { resolve(tran) }, | |||
| (tx, err) => { reject(err) } | |||
| ) | |||
| }) | |||
| return myPromise | |||
| } | |||
| /** | |||
| * 提交一个事务 | |||
| * @param { connection } tran 开启事务时创建的连接对象 | |||
| * @returns 提交事务 | |||
| */ | |||
| commit (tran) { | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| // 提交事务 | |||
| tran.commit((err) => { | |||
| if (err) { | |||
| console.log('事务提交失败', err) | |||
| reject(err) | |||
| } else { | |||
| resolve() | |||
| } | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| /** | |||
| * 关闭数据库 | |||
| * @param { connection } tran 开启事务时创建的连接对象 | |||
| */ | |||
| close (tran = null) { | |||
| if (tran !== null) { | |||
| // 归还连接对象。console.log('--close: tran', tran.threadId) | |||
| tran.release() | |||
| // console.log('\n[MySQL 事务,已经关闭数据库:] \n') | |||
| } else { | |||
| // 关闭连接 | |||
| this.db.end((err) => { | |||
| if (err) { | |||
| console.error('关闭连接发生错误:', err) | |||
| } else { | |||
| // console.log('\n[MySQL 已经关闭数据库:]\n') | |||
| } | |||
| }) | |||
| } | |||
| } | |||
| /** | |||
| * 添加一条记录 | |||
| * @param {string} meta 表名 | |||
| * @param {object} model 要添加的记录 | |||
| * @param {*} tran 事务,可以为null | |||
| * @returns | |||
| */ | |||
| addModel (meta, model, tran = null) { | |||
| return _addModel(this, meta, model, tran) | |||
| } | |||
| /** | |||
| * 修改一条记录 | |||
| * @param {string} meta 表名 | |||
| * @param {object} model 要添加的记录 | |||
| * @param {*} tran 事务,可以为null | |||
| * @returns | |||
| */ | |||
| updateModel (meta, model, tran = null) { | |||
| return _updateModel(this, meta, model, tran) | |||
| } | |||
| /** | |||
| * 删除一条记录 | |||
| * @param {string} tableName 表名 | |||
| * @param {object} model 要添加的记录 | |||
| * @param {*} tran 事务,可以为null | |||
| * @returns | |||
| */ | |||
| delModel (meta, model, tran = null) { | |||
| return _deleteModel(this, meta, model, tran) | |||
| } | |||
| /** | |||
| * 获取一条记录 | |||
| * @param {string} tableName 表名 | |||
| * @param {object} model 要添加的记录 | |||
| * @param {*} tran 事务,可以为null | |||
| * @returns | |||
| */ | |||
| getModel (meta, model, tran = null) { | |||
| return _getModel(this, meta, model, tran) | |||
| } | |||
| /** | |||
| * 获取全部记录,可以查询 | |||
| * @param {string} tableName 表名 | |||
| * @param {object} model 要添加的记录 | |||
| * @param {*} tran 事务,可以为null | |||
| * @returns | |||
| */ | |||
| listAll (meta, query, pager = {}, tran = null) { | |||
| return _listAll(this, meta, query, pager, tran) | |||
| } | |||
| /** | |||
| * 分页获取记录,可以查询 | |||
| * @param {string} tableName 表名 | |||
| * @param {object} model 要添加的记录 | |||
| * @param {*} tran 事务,可以为null | |||
| * @returns | |||
| */ | |||
| async listPager (meta, query, pager, _count = 0, tran = null) { | |||
| const count = _count === 0 ? await _listCount(this, meta, query, tran) : _count | |||
| const list = await _listPager(this, meta, query, pager, tran) | |||
| return { | |||
| count, | |||
| list | |||
| } | |||
| } | |||
| } | |||
| MySQLHelp.prototype.add = _addModel | |||
| @@ -0,0 +1,152 @@ | |||
| import webSQL from './help.js' | |||
| // 维护 | |||
| import createTable from './table-create.js' | |||
| import deleteTable from './table-delete.js' | |||
| export default { | |||
| _webSQLFlag: Symbol('nf-webSQL-help'), | |||
| _help: {}, // 访问数据库的实例 | |||
| _tables: {}, // 把表变成对象 | |||
| /** | |||
| * 根据参数创建一个数据库的实例,初始化数据库 | |||
| * * 删表、建表、添加默认数据 | |||
| * @param {*} info 参数 | |||
| * @returns 安装一个Vue的插件 | |||
| * * dbFlag: '数据库标识', | |||
| * * dbConfig: { // 连接数据库 | |||
| * * * dbName: 'vite2-blog', | |||
| * * * ver: 1.0, | |||
| * * * remarks: '测试用的博客数据库', | |||
| * * * size: 2 | |||
| * * }, | |||
| * * init: () => {}, | |||
| * * tables: { | |||
| * * * tableName: ['字段名称', '字段名称'] | |||
| * * }, | |||
| * * isDeleteOldTable: false, // 是否删除之前的表 | |||
| */ | |||
| createHelp (info) { | |||
| let webSQLFlag = this._webSQLFlag | |||
| if (typeof info.dbFlag === 'string') { | |||
| webSQLFlag = Symbol.for(info.dbFlag) | |||
| } else if (typeof info.dbFlag === 'symbol') { | |||
| webSQLFlag = info.dbFlag | |||
| } | |||
| const init = info.init | |||
| // const tables = this._tables | |||
| // 连接数据库 | |||
| // eslint-disable-next-line new-cap | |||
| const help = new webSQL(info.dbConfig) | |||
| // 遍历配置,设置表的操作。 | |||
| // 按照表(对象)的配置信息,设置操作实例 | |||
| help.begin().then((cn) => { | |||
| for (const key in info.tables) { | |||
| const tableName = key | |||
| const cols = Object.keys(info.tables[key]) | |||
| // 判断要不要删除表 | |||
| if (info.isDeleteOldTable) { | |||
| // 删除表 | |||
| deleteTable(help, tableName, cn) | |||
| } | |||
| // 建立表 | |||
| createTable(help, tableName, cols, cn) | |||
| } | |||
| }) | |||
| this._help[webSQLFlag] = help | |||
| const newTable = {} | |||
| help._tables = newTable | |||
| this._tables[webSQLFlag] = newTable | |||
| // 把表变成对象 | |||
| for (const key in info.tables) { | |||
| const meta = { | |||
| tableName: key, | |||
| cols: info.tables[key] | |||
| } | |||
| newTable[meta.tableName] = { | |||
| add: (model, cn = null) => help.addModel(meta, model, cn), | |||
| get: (id = null, cn = null) => help.getModel(meta, id, cn), | |||
| put: (model, cn = null) => { | |||
| let _id = model | |||
| if (typeof model === 'object') { | |||
| _id = model[info.stores[key].id] | |||
| } | |||
| return help.updateModel(meta, model, _id, cn) | |||
| }, | |||
| del: (model, cn = null) => { | |||
| let _id = model | |||
| if (typeof model === 'object') { | |||
| _id = model[info.stores[key].id] | |||
| } | |||
| return help.delModel(meta, _id, cn) | |||
| }, | |||
| list: (query = {}, isDesc = false, cn = null) => { | |||
| const pager = { | |||
| orderBy: {} | |||
| } | |||
| pager.orderBy[Object.keys(meta.cols)[0]] = isDesc | |||
| return help.listAll(meta, query, pager, cn) | |||
| }, | |||
| pager: (query = {}, _pager = null, _count = 0, cn = null) => { | |||
| const pager = { | |||
| pagerIndex: 1, | |||
| pagerSize: 5, | |||
| pagerTotal: 100, | |||
| orderBy: {} | |||
| } | |||
| pager.orderBy[Object.keys(meta.cols)[0]] = false | |||
| if (_pager !== null){ | |||
| Object.assign(pager, _pager) | |||
| } | |||
| return help.listPager(meta, query, pager, _count, cn) | |||
| }, | |||
| begin: () => help.begin() | |||
| } | |||
| } | |||
| if (typeof init === 'function') { | |||
| init(help, newTable) | |||
| } | |||
| return { | |||
| // 安装插件,不用 provide 注入了 | |||
| install (app, options) { | |||
| // 注入状态,用 symbol 作为标记,避免重名 | |||
| // app.provide(webSQLFlag, { help, tables }) | |||
| // 调用初始化,给全局状态赋值 | |||
| } | |||
| } | |||
| }, | |||
| // 获取数据库的连接实例 | |||
| useSQLHelp (_dbFlag) { | |||
| let flag = this._webSQLFlag | |||
| if (typeof _dbFlag === 'string') { | |||
| flag = Symbol.for(_dbFlag) | |||
| } else if (typeof _dbFlag === 'symbol') { | |||
| flag = _dbFlag | |||
| } | |||
| return this._help[flag] | |||
| }, | |||
| /** | |||
| * 把表变成对象,可以直接用表.add/put/del/get等操作 | |||
| * @param {*} _dbFlag | |||
| * @returns | |||
| */ | |||
| useTables (_dbFlag) { | |||
| let flag = this._webSQLFlag | |||
| if (typeof _dbFlag === 'string') { | |||
| flag = Symbol.for(_dbFlag) | |||
| } else if (typeof _dbFlag === 'symbol') { | |||
| flag = _dbFlag | |||
| } | |||
| return this._tables[flag] | |||
| } | |||
| } | |||
| @@ -0,0 +1,48 @@ | |||
| import _getWhereQuery from './_where-query.js' | |||
| import _getPager from './_pager-info.js' | |||
| /** | |||
| * 不分页获取数据,可以查询 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { Object } meta 表、字段 | |||
| * @param { Object } query 查询条件 | |||
| * @param { Object } pager 排序字段 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * cols:{colName: '类型'}, 需要显示的字段 | |||
| * * query 结构(查询条件): | |||
| * * * { colName: [401, 11] } 字段名称,查询方式,查询关键字 | |||
| * * pager 结构: | |||
| * * * orderBy: { id: false } // 排序字段:字段名,false表示倒序。 | |||
| */ | |||
| export default function listAll (help, meta, query, pager, cn = null) { | |||
| // console.log('开始获取全部记录 :') | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| // 查询条件和查询参数 | |||
| const { whereQuery, whereValue } = _getWhereQuery(query) | |||
| // 设置排序 | |||
| const { orderBy } = _getPager(pager) | |||
| // 设置显示的字段 | |||
| const showCol = Object.keys(meta.cols) | |||
| if (showCol.length === 0) { showCol.push('*') } | |||
| // 拼接查询语句 | |||
| const sql = `SELECT ${showCol.join(',')} FROM ${meta.tableName} ${whereQuery} ${orderBy}` | |||
| // console.log('select-all-sql:', sql, whereValue) | |||
| help.query(sql, whereValue, cn) | |||
| .then((res) => { | |||
| // 添加成功 | |||
| // console.log('分页获取记录:', res) | |||
| resolve(Array.from(res.rows)) | |||
| }) | |||
| .catch((err) => { | |||
| // 出错了 | |||
| console.log('获取全部记录失败了:', err) | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| import _getWhereQuery from './_where-query.js' | |||
| import _getPager from './_pager-info.js' | |||
| /** | |||
| * 分页获取数据,可以查询 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { Object } meta 表、字段 | |||
| * @param { Object } query 查询条件 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * cols:{colName: '类型'}, 需要显示的字段 | |||
| * * query 结构(查询条件): | |||
| * * * { colName: [401, '查询关键字'] } 字段名称,查询方式,查询关键字 | |||
| */ | |||
| export default function getCount (help, meta, query) { | |||
| return new Promise((resolve, reject) => { | |||
| // 查询条件和查询参数 | |||
| const { whereQuery, whereValue } = _getWhereQuery(query) | |||
| // 统计总数 | |||
| const sql = `SELECT count(1) as count FROM ${meta.tableName} ${whereQuery} ` | |||
| console.log('count-sql:', sql, whereValue) | |||
| help.query(sql, whereValue).then((re) => { | |||
| resolve(re.rows[0].count) | |||
| }).catch((err) => { | |||
| // 出错了 | |||
| console.log('统计总记录数失败了:', err) | |||
| reject(err) | |||
| }) | |||
| }) | |||
| } | |||
| @@ -0,0 +1,51 @@ | |||
| import _getWhereQuery from './_where-query.js' | |||
| import _getPager from './_pager-info.js' | |||
| /** | |||
| * 分页获取数据,可以查询 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { Object } meta 表、字段 | |||
| * @param { Object } query 查询条件 | |||
| * @param { Object } pager 数据 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * cols:{colName: '类型'}, 需要显示的字段 | |||
| * * query 结构(查询条件): | |||
| * * * { colName: [401, 11] } 字段名称,查询方式,查询关键字 | |||
| * * pager 结构: | |||
| * * * pageSize: 20 // 一页显示多少条记录 | |||
| * * * orderBy: { id: false } // 排序字段:字段名,false表示倒序。 | |||
| * * * pageTotal: 100 // 符合查询条件的总记录数 | |||
| * * * pageIndex: 1 // 显示第几页的记录,从 1 开始 | |||
| */ | |||
| export default function listPager (help, meta, query, pager) { | |||
| // console.log('开始分页 :') | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| // 查询条件和查询参数 | |||
| const { whereQuery, whereValue } = _getWhereQuery(query) | |||
| // 设置排序和分页 | |||
| const { orderBy, limit } = _getPager(pager) | |||
| // 设置显示的字段 | |||
| const showCol = Object.keys(meta.cols) | |||
| if (showCol.length === 0) { showCol.push('*') } | |||
| // 拼接查询语句 | |||
| const sql = `SELECT ${showCol.join(',')} FROM ${meta.tableName} ${whereQuery} ${orderBy} ${limit}` | |||
| console.log('select-pager-sql:', sql, whereValue) | |||
| help.query(sql, whereValue) | |||
| .then((res) => { | |||
| // 添加成功 | |||
| // console.log('分页获取记录:', res) | |||
| resolve(Array.from(res.rows)) | |||
| }) | |||
| .catch((err) => { | |||
| // 出错了 | |||
| console.log('分页获取记录失败了:', err) | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,40 @@ | |||
| /** | |||
| * 实现删除数据的功能。逻辑删除,update set flag = 1 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { string } tableName 表名 | |||
| * @param { array } cols 字段名集合,数组 | |||
| * @param { connection } cn 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * idKey: 'id', 主键字段名称 | |||
| * * * cols: {name: ''}, | |||
| */ | |||
| export default function createTable (help, tableName, cols, cn = null) { | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| // 记录字段名称,不设置类型了。 | |||
| let _cols = [] | |||
| if (typeof cols.length === 'number') { | |||
| _cols = cols | |||
| } else { | |||
| _cols = Object.keys(cols) | |||
| } | |||
| _cols = _cols.filter(key => key.toLowerCase() !== 'id') | |||
| const sql = `CREATE TABLE IF NOT EXISTS ${tableName} (id INTEGER PRIMARY KEY ASC, ${_cols.join(',')} )` | |||
| // console.log('createSQL:', sql) | |||
| // 调用事务,建立表 | |||
| help.query(sql, [], cn) | |||
| .then((res) => { | |||
| resolve(res) | |||
| }) | |||
| .catch((err) => { | |||
| console.log('createTable -sql:', sql, err) | |||
| const stack = new Error() | |||
| console.log('createTable -sql:', stack) | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,28 @@ | |||
| /** | |||
| * 实现删除数据的功能。逻辑删除,update set flag = 1 | |||
| * @param { MySQLHelp } help 访问数据库的实例 | |||
| * @param { string } tableName 表名 | |||
| * @param { connection } cn 如果使用事务的话,需要传递开启事务时创建的连接对象 | |||
| * @returns 添加记录的ID | |||
| * * meta 结构: | |||
| * * * tableName: '', 表名 | |||
| * * * idKey: 'id', 主键字段名称 | |||
| * * * delFlag: 'isDel', 逻辑删除,标记字段名称 | |||
| */ | |||
| export default function deleteTable (help, tableName, cn = null) { | |||
| const myPromise = new Promise((resolve, reject) => { | |||
| const sql = `DROP TABLE ${tableName} ` | |||
| // console.log('sql:', sql) | |||
| help.query(sql, [], cn) | |||
| .then((res) => { | |||
| // 成功了,返回给调用者 | |||
| resolve(res) | |||
| }) | |||
| .catch((err) => { | |||
| console.log('deleteTable - sql:', sql, err) | |||
| reject(err) | |||
| }) | |||
| }) | |||
| return myPromise | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| // 引入各种函数,便于做成npm包 | |||
| // indexedDB 部分 | |||
| import dbHelp from './nf-ws-indexeddb/help.js' | |||
| import dbInstall from './nf-ws-indexeddb/install.js' | |||
| // webSQL 部分 | |||
| import sqlHelp from './nf-ws-websql/help.js' | |||
| import sqlInstall from './nf-ws-websql/install.js' | |||
| // indexedDB 部分 | |||
| const dbCreateHelp = (info) => dbInstall.createHelp(info) | |||
| const useDBHelp = (_dbFlag) => dbInstall.useDBHelp(_dbFlag) | |||
| const useStores = (_dbFlag) => dbInstall.useStores(_dbFlag) | |||
| // webSQL 部分 | |||
| const sqlCreateHelp = (info) => sqlInstall.createHelp(info) | |||
| const useSQLHelp = (_dbFlag) => sqlInstall.useSQLHelp(_dbFlag) | |||
| const useTables = (_dbFlag) => sqlInstall.useTables(_dbFlag) | |||
| export { | |||
| // webSQL部分 | |||
| sqlHelp, | |||
| sqlCreateHelp, | |||
| useSQLHelp, | |||
| useTables, | |||
| // indexedDB 部分 | |||
| dbHelp, // indexedDB 的help | |||
| dbCreateHelp, // 创建help,初始化设置 | |||
| useDBHelp, // 组件里获取 help | |||
| useStores // 组件里获取对象仓库,方便实现增删改查 | |||
| } | |||
| @@ -0,0 +1,126 @@ | |||
| const manageStorage = (type) => { | |||
| // type --- local: localStorage; | |||
| // session:sessionStorage | |||
| if (typeof type === 'undefined' || type === '') { type = 'local' } | |||
| // 设置值 | |||
| const setItem = (key, value) => { | |||
| let v = value | |||
| // 记录value的类型,默认是对象/数组 | |||
| let valueType = typeof value | |||
| // 依据类型做序列化 | |||
| switch (valueType) { | |||
| case 'object': | |||
| // 判断是不是日期类型 | |||
| if (value === null) { | |||
| valueType = 'null' | |||
| v = 'null' | |||
| } else if (value instanceof Date) { | |||
| // 保存数据的时间戳 | |||
| valueType = 'date' | |||
| v = value.valueOf() | |||
| } else { | |||
| // 对象、数组 | |||
| v = JSON.stringify(value) | |||
| } | |||
| break | |||
| case 'function': | |||
| v = value.toString() | |||
| break | |||
| case 'undefined': | |||
| valueType = 'undefined' | |||
| v = 'undefined' | |||
| break | |||
| } | |||
| // 把数据、数据类型和时间戳,一起保存 | |||
| const object = { | |||
| valueType: valueType, | |||
| time: new Date().valueOf(), // 时间戳,判断是否过期 | |||
| value: v | |||
| } | |||
| v = JSON.stringify(object) | |||
| if (type === 'local') { | |||
| localStorage.setItem(key, v) | |||
| } else { | |||
| sessionStorage.setItem(key, v) | |||
| } | |||
| } | |||
| // 获取值 | |||
| const getItem = (key) => { | |||
| let str = '' | |||
| // 判断存储方式 | |||
| if (type === 'local') { | |||
| str = localStorage.getItem(key) | |||
| } else { | |||
| str = sessionStorage.getItem(key) | |||
| } | |||
| // 判断是否为空 | |||
| if (typeof str === 'undefined' || str === null || str === '') { | |||
| return str | |||
| } | |||
| // 判断格式是否符合,没有太好的办法,暂时先这样。 | |||
| if (str.indexOf('{"valueType":"') === -1) { | |||
| return '' | |||
| } | |||
| console.log('-----------------------------------------') | |||
| console.log('111存储的数据的类型:', typeof str) | |||
| console.log('111存储的数据:', str) | |||
| // 把存储的数据转换为对象 | |||
| const object = JSON.parse(str) | |||
| // 取值 | |||
| let value = object.value | |||
| // 判断存储之前的类型,做转换 | |||
| switch (object.valueType) { | |||
| case 'object':// 对象和数组 | |||
| value = JSON.parse(value) | |||
| break | |||
| case 'function': // 不做转换 | |||
| // value = object.value | |||
| break | |||
| case 'date': // 日期的时间戳 | |||
| value = new Date(value) | |||
| break | |||
| case 'number': // 数字 | |||
| value = parseInt(value) | |||
| break | |||
| case 'null': | |||
| value = null | |||
| break | |||
| case 'undefined': | |||
| value = undefined | |||
| break | |||
| } | |||
| console.log('存储的数据的类型:') | |||
| console.log(object.valueType, typeof value) | |||
| console.log(object.valueType, Object.prototype.toString.call(value)) | |||
| console.log('存储的数据:', value) | |||
| return value | |||
| } | |||
| // removeItem | |||
| const removeItem = (key) => { | |||
| if (type === 'local') { | |||
| localStorage.removeItem(key) | |||
| } else { | |||
| sessionStorage.removeItem(key) | |||
| } | |||
| } | |||
| // clear | |||
| const clear = (key) => { | |||
| if (type === 'local') { | |||
| localStorage.clear() | |||
| } else { | |||
| sessionStorage.clear() | |||
| } | |||
| } | |||
| return { | |||
| setItem, | |||
| getItem, | |||
| removeItem, | |||
| clear | |||
| } | |||
| } | |||
| @@ -0,0 +1,452 @@ | |||
| // indexedDB.js,浏览器本地数据库操作 | |||
| export default { | |||
| // indexedDB兼容 | |||
| indexedDB: window.indexedDB || window.webkitindexedDB || window.msIndexedDB || mozIndexedDB, | |||
| // 打开数据库 | |||
| // 新对象储存空间newStore参数:newStore.name、newStore.key | |||
| // 新增对象存储空间要更改数据库版本 | |||
| openDB: function (dbname, version, db, newStore, callback) { | |||
| var version = version; | |||
| var request = this.indexedDB.open(dbname, version); | |||
| request.onerror = function (event) { | |||
| console.log('IndexedDB数据库打开错误'); | |||
| }; | |||
| request.onsuccess = function (event) { | |||
| db = event.target.result; | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(db); | |||
| } | |||
| }; | |||
| // onupgradeneeded,调用创建新的储存空间 | |||
| request.onupgradeneeded = function (event) { | |||
| var db = event.target.result; | |||
| if (newStore) { | |||
| if (!db.objectStoreNames.contains(newStore.name)) { | |||
| var objectStore = db.createObjectStore(newStore.name, { | |||
| keyPath: newStore.key, | |||
| }); | |||
| objectStore.createIndex('counter_index', 'counter', { unique: false }); | |||
| objectStore.createIndex('barcode_index', 'barcode', { unique: false }); | |||
| objectStore.createIndex('qty_index', 'qty', { unique: false }); | |||
| objectStore.createIndex('counter_code', ['counter', 'barcode'], { unique: false }); | |||
| } | |||
| } | |||
| }; | |||
| }, | |||
| // 删除数据库 | |||
| deleteDB: function (dbname, callback) { | |||
| var deleteQuest = this.indexedDB.deleteDatabase(dbname); | |||
| deleteQuest.onerror = function () { | |||
| console.log('删除数据库出错'); | |||
| }; | |||
| deleteQuest.onsuccess = function () { | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(); | |||
| } | |||
| } | |||
| }, | |||
| // 关闭数据库 | |||
| closeDB: function (dbname) { | |||
| dbname.close(); | |||
| console.log('数据库已关闭'); | |||
| }, | |||
| // 更新旧值,针对输入数量 | |||
| putData: function (db, storename, dataArr, callback) { | |||
| let mybarcode = ""; | |||
| let QTY = ""; | |||
| let key = ""; | |||
| let counter = ""; | |||
| let barcode = ""; | |||
| let addtime = ""; | |||
| dataArr.forEach(item => { | |||
| mybarcode = item.barcode; | |||
| QTY = item.qty; | |||
| barcode = item.barcode; | |||
| counter = item.counter; | |||
| key = item.counterCode; | |||
| addtime = item.addtime; | |||
| }); | |||
| this.getdatabycursor(db, storename).then(arr => { | |||
| if (arr.length == 0) { | |||
| //console.log("添加") | |||
| var store = db.transaction(storename, 'readwrite').objectStore(storename), | |||
| request; | |||
| for (var i = 0, len = dataArr.length; i < len; i++) { | |||
| request = store.put(dataArr[i]); | |||
| request.onerror = function () { | |||
| console.error('PUT添加数据报错'); | |||
| }; | |||
| request.onsuccess = function (result) { | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(); | |||
| } | |||
| }; | |||
| } | |||
| } | |||
| else { | |||
| this.read(db, storename, counter, barcode).then(x => { | |||
| if (x) { | |||
| //console.log("最新的值是" + QTY) | |||
| this.updateDataByKey(db, storename, key, QTY, addtime).then(x => { | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(); | |||
| } | |||
| }); | |||
| } | |||
| else { | |||
| //console.log("再次添加") | |||
| var store = db.transaction(storename, 'readwrite').objectStore(storename), | |||
| request; | |||
| for (var i = 0, len = dataArr.length; i < len; i++) { | |||
| request = store.put(dataArr[i]); | |||
| request.onerror = function () { | |||
| console.error('PUT添加数据报错'); | |||
| }; | |||
| request.onsuccess = function (result) { | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(); | |||
| } | |||
| }; | |||
| } | |||
| } | |||
| }) | |||
| } | |||
| }) | |||
| }, | |||
| // 更新旧值 | |||
| putDatas: function (db, storename, dataArr, callback) { | |||
| let mybarcode = ""; | |||
| let QTY = ""; | |||
| let key = ""; | |||
| let counter = ""; | |||
| let barcode = ""; | |||
| let addtime = ""; | |||
| dataArr.forEach(item => { | |||
| mybarcode = item.barcode; | |||
| QTY = item.qty; | |||
| key = item.counterCode; | |||
| counter = item.counter; | |||
| barcode = item.barcode; | |||
| addtime = item.addtime; | |||
| }); | |||
| this.getdatabycursor(db, storename).then(arr => { | |||
| if (arr.length == 0) { | |||
| //console.log("添加") | |||
| var store = db.transaction(storename, 'readwrite').objectStore(storename), | |||
| request; | |||
| for (var i = 0, len = dataArr.length; i < len; i++) { | |||
| request = store.add(dataArr[i]); | |||
| request.onerror = function () { | |||
| console.error('PUT添加数据报错'); | |||
| }; | |||
| request.onsuccess = function (result) { | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(); | |||
| } | |||
| }; | |||
| } | |||
| } | |||
| else { | |||
| this.read(db, storename, counter, barcode).then(x => { | |||
| if (x) { | |||
| this.updateDataByKeys(db, storename, key, addtime).then(x => { | |||
| this.getdata(db, storename).then(result => { | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(); | |||
| } | |||
| }); | |||
| }); | |||
| } | |||
| else { | |||
| //console.log("再次添加") | |||
| //console.log("当前的值是"+barcode) | |||
| var store = db.transaction(storename, 'readwrite').objectStore(storename), | |||
| request; | |||
| for (var i = 0, len = dataArr.length; i < len; i++) { | |||
| request = store.add(dataArr[i]); | |||
| request.onerror = function () { | |||
| console.error('PUT添加数据报错'); | |||
| }; | |||
| request.onsuccess = function (result) { | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(); | |||
| } | |||
| }; | |||
| } | |||
| } | |||
| }) | |||
| } | |||
| }) | |||
| }, | |||
| //根据key修改数量 | |||
| updateDataByKey: function (db, storeName, value, QTY, addtime) { | |||
| var transaction = db.transaction(storeName, 'readwrite'); | |||
| var store = transaction.objectStore(storeName); | |||
| var request = store.get(value); | |||
| return new Promise((resolve, reject) => { | |||
| request.onsuccess = function (e) { | |||
| var stocktable = e.target.result; | |||
| if (stocktable) { | |||
| stocktable.qty = QTY; | |||
| stocktable.addtime = addtime; | |||
| resolve(store.put(stocktable)); | |||
| } | |||
| else { | |||
| reject(false); | |||
| } | |||
| }; | |||
| }) | |||
| }, | |||
| updateDataBycode: function (db, storeName, value, QTY) { | |||
| var transaction = db.transaction(storeName, 'readwrite'); | |||
| var store = transaction.objectStore(storeName); | |||
| var request = store.get(value); | |||
| return new Promise((resolve, reject) => { | |||
| request.onsuccess = function (e) { | |||
| var stocktable = e.target.result; | |||
| if (stocktable) { | |||
| stocktable.qty = QTY; | |||
| resolve(store.put(stocktable)); | |||
| } | |||
| else { | |||
| reject(false); | |||
| } | |||
| }; | |||
| }) | |||
| }, | |||
| //根据key修改数量 | |||
| updateDataByKeys: function (db, storeName, value, addtime, callback) { | |||
| var transaction = db.transaction(storeName, 'readwrite'); | |||
| var store = transaction.objectStore(storeName); | |||
| var request = store.get(value); | |||
| return new Promise((resolve, reject) => { | |||
| //console.log(addtime) | |||
| request.onsuccess = function (e) { | |||
| var stocktable = e.target.result; | |||
| if (stocktable) { | |||
| stocktable.qty = QTY ; | |||
| stocktable.addtime = addtime; | |||
| resolve(store.put(stocktable)); | |||
| } | |||
| else { | |||
| reject(false); | |||
| } | |||
| }; | |||
| }) | |||
| }, | |||
| // 删除数据 | |||
| deleteData: function (db, storename, key, callback) { | |||
| var store = db.transaction(storename, 'readwrite').objectStore(storename); | |||
| store.delete(key); | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(); | |||
| } | |||
| }, | |||
| // 清空数据 | |||
| clearData: function (db, storename, callback) { | |||
| var store = db.transaction(storename, 'readwrite').objectStore(storename); | |||
| store.clear(); | |||
| if (callback && (typeof callback === 'function')) { | |||
| callback(); | |||
| } | |||
| }, | |||
| // 通过key获取数据 | |||
| read: function (db, storeName, counter, barcode) { | |||
| var transaction = db.transaction(storeName); | |||
| var objectStore = transaction.objectStore(storeName); | |||
| var currentdata = [counter, barcode]; | |||
| var indexs = objectStore.index('counter_code'); | |||
| var request = indexs.openCursor(IDBKeyRange.only(currentdata)); | |||
| return new Promise((resolve, reject) => { | |||
| request.onsuccess = function (e) { | |||
| var cursor = e.target.result; | |||
| if (cursor) { | |||
| resolve(true); | |||
| } | |||
| else { | |||
| resolve(false); | |||
| } | |||
| } | |||
| }) | |||
| }, | |||
| // 通过barcode获取数据 | |||
| reads: function (db, storeName, values) { | |||
| var transaction = db.transaction(storeName); | |||
| var objectStore = transaction.objectStore(storeName); | |||
| var indexs = objectStore.index('barcode_index'); | |||
| var data = []; | |||
| var request = indexs.openCursor(IDBKeyRange.only(values)); | |||
| return new Promise((resolve, reject) => { | |||
| request.onsuccess = function (e) { | |||
| var cursor = e.target.result; | |||
| if (cursor) { | |||
| data.push(cursor.value); | |||
| // resolve(data); | |||
| cursor.continue(); | |||
| } | |||
| else { | |||
| resolve(data) | |||
| } | |||
| }; | |||
| }) | |||
| }, | |||
| //根据counter索引查询数据 | |||
| getdatabyCounter: function (db, storeName, values) { | |||
| var transaction = db.transaction(storeName); | |||
| var store = transaction.objectStore(storeName); | |||
| var indexs = store.index('counter_index'); | |||
| var datas = []; | |||
| var request = indexs.openCursor(IDBKeyRange.only(values)) | |||
| return new Promise((resolve, reject) => { | |||
| request.onsuccess = function (e) { | |||
| var cursor = e.target.result; | |||
| if (cursor) { | |||
| datas.push(cursor.value); | |||
| cursor.continue(); | |||
| } | |||
| else { | |||
| resolve(datas) | |||
| } | |||
| } | |||
| }) | |||
| }, | |||
| //根据主键和索引查询 | |||
| getAll: function (db, storeName, counter, barcode) { | |||
| var transaction = db.transaction(storeName); | |||
| var objectStore = transaction.objectStore(storeName); | |||
| var counterCode = [counter, barcode]; | |||
| var indexs = objectStore.index('counter_code'); | |||
| var request = indexs.openCursor(IDBKeyRange.only(counterCode)); | |||
| var data = []; | |||
| return new Promise((resolve, reject) => { | |||
| request.onsuccess = function (e) { | |||
| var cursor = e.target.result; | |||
| if (cursor) { | |||
| data.push(cursor.value); | |||
| //resolve(data); | |||
| cursor.continue(); | |||
| } | |||
| else { | |||
| resolve(data) | |||
| } | |||
| } | |||
| }) | |||
| }, | |||
| //根据key查询数量是否存在 | |||
| getqtyBykey: function (db, storeName, key) { | |||
| var transaction = db.transaction(storeName); | |||
| var objectStore = transaction.objectStore(storeName); | |||
| var request = objectStore.get(key); | |||
| request.onerror = function (event) { | |||
| console.log('事务失败'); | |||
| }; | |||
| return new Promise((resolve, reject) => { | |||
| request.onsuccess = function (event) { | |||
| if (request.result) { | |||
| //console.log(request.result.qty) | |||
| resolve(request.result); | |||
| } else { | |||
| resolve(false); | |||
| } | |||
| }; | |||
| }) | |||
| }, | |||
| // //通过游标遍历数据 | |||
| getdatabycursor: function (db, storename) { | |||
| var objectStore = db.transaction(storename).objectStore(storename); | |||
| var dataList = []; | |||
| var i = 0; | |||
| return new Promise((resolve, reject) => { | |||
| objectStore.openCursor().onsuccess = function (event) { | |||
| var cursor = event.target.result; | |||
| if (cursor) { | |||
| dataList.push(cursor.value) | |||
| cursor.continue(); | |||
| } else { | |||
| resolve(dataList); | |||
| } | |||
| }; | |||
| }) | |||
| }, | |||
| //查询所有的柜台 | |||
| getAllCounter: function (db, storename) { | |||
| var transaction = db.transaction(storename); | |||
| var store = transaction.objectStore(storename); | |||
| var indexs = store.index('counter_index'); | |||
| var data = []; | |||
| return new Promise((resolve, reject) => { | |||
| indexs.openCursor().onsuccess = function (e) { | |||
| var cursor = e.target.result; | |||
| if (cursor) { | |||
| // console.log(cursor.value.counter); | |||
| data.push(cursor.value.counter); | |||
| resolve(data); | |||
| cursor.continue(); | |||
| } | |||
| } | |||
| }) | |||
| }, | |||
| getdata: function (db, storename) { | |||
| var objectStore = db.transaction(storename).objectStore(storename); | |||
| var data = []; | |||
| return new Promise((resolve, reject) => { | |||
| objectStore.openCursor().onsuccess = function (event) { | |||
| var cursor = event.target.result; | |||
| if (cursor) { | |||
| data.push(cursor.value) | |||
| resolve(data) | |||
| } | |||
| else { | |||
| reject(false) | |||
| } | |||
| }; | |||
| }) | |||
| }, | |||
| getqtybyqtyindex: function (db, storename) { | |||
| var transaction = db.transaction(storename); | |||
| var store = transaction.objectStore(storename); | |||
| var indexs = store.index('qty_index'); | |||
| var sum = 0; | |||
| return new Promise((resolve, reject) => { | |||
| indexs.openCursor().onsuccess = function (e) { | |||
| var cursor = e.target.result; | |||
| if (cursor) { | |||
| sum += cursor.value.qty | |||
| cursor.continue(); | |||
| } | |||
| else { | |||
| resolve(sum) | |||
| } | |||
| } | |||
| }) | |||
| } | |||
| } | |||
| @@ -0,0 +1,10 @@ | |||
| import Vue from "vue"; | |||
| import VueLazyload from "vue-lazyload"; | |||
| // https://github.com/hilongjw/vue-lazyload | |||
| Vue.use(VueLazyload, { | |||
| preLoad: 1.3, | |||
| // loading: require("@/assets/ic_photo_loading.png"), | |||
| error: require("@/assets/ic_photo_error.png"), | |||
| attempt: 3 | |||
| }); | |||
| @@ -0,0 +1,16 @@ | |||
| import Vue from "vue"; | |||
| import { Indicator } from "mint-ui"; | |||
| // Mint UI 使用文档: https://mint-ui.github.io/docs/#/zh-cn2 | |||
| Vue.component(Indicator); | |||
| // import isEmpty from "lodash/isEmpty"; | |||
| Vue.prototype.showLoading = function(msg) { | |||
| // if (isEmpty(msg)) { | |||
| // msg = "加载中..."; | |||
| // } | |||
| return Indicator.open(msg); | |||
| }; | |||
| Vue.prototype.hideLoading = function() { | |||
| return Indicator.close(); | |||
| }; | |||
| @@ -0,0 +1,149 @@ | |||
| var websock = null; | |||
| let rec; //断线重连后,延迟5秒重新创建WebSocket连接 rec用来存储延迟请求的代码 | |||
| let isConnect = false; //连接标识 避免重复连接 | |||
| let checkMsg = "heartbeat"; //心跳发送/返回的信息 服务器和客户端收到的信息内容如果如下 就识别为心跳信息 不要做业务处理 | |||
| var globalCallback = function() {}; | |||
| let createWebSocket = (url) => { | |||
| try { | |||
| initWebSocket(url); //初始化websocket连接 | |||
| } catch (e) { | |||
| console.log("尝试创建连接失败"); | |||
| reConnect(url); //如果无法连接上webSocket 那么重新连接!可能会因为服务器重新部署,或者短暂断网等导致无法创建连接 | |||
| } | |||
| }; | |||
| //定义重连函数 | |||
| let reConnect = (url) => { | |||
| console.log("尝试重新连接"); | |||
| if (isConnect) return; //如果已经连上就不在重连了 | |||
| rec && clearTimeout(rec); | |||
| rec = setTimeout(function() { | |||
| // 延迟5秒重连 避免过多次过频繁请求重连 | |||
| createWebSocket(url); | |||
| }, 5000); | |||
| }; | |||
| //设置关闭连接 | |||
| let closeWebSocket = () => { | |||
| webSocket.close(); | |||
| }; | |||
| //心跳设置 | |||
| var heartCheck = { | |||
| timeout: 20000, //每段时间发送一次心跳包 这里设置为20s | |||
| timeoutObj: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象) | |||
| start: function() { | |||
| this.timeoutObj = setTimeout(function() { | |||
| if (isConnect) websock.send(checkMsg); | |||
| }, this.timeout); | |||
| }, | |||
| reset: function() { | |||
| clearTimeout(this.timeoutObj); | |||
| this.start(); | |||
| } | |||
| }; | |||
| // 初始化websocket | |||
| function initWebSocket(ws) { | |||
| // ws地址 -->这里是你的请求路径 | |||
| websock = new WebSocket(ws); | |||
| websock.onmessage = function(e) { | |||
| websocketonmessage(e); | |||
| }; | |||
| websock.onclose = function(e) { | |||
| websocketclose(e); | |||
| }; | |||
| websock.onopen = function() { | |||
| websocketOpen(); | |||
| // heartCheck.start(); | |||
| }; | |||
| // 连接发生错误的回调方法 | |||
| websock.onerror = function() { | |||
| console.log("WebSocket连接发生错误"); | |||
| isConnect = false; //连接断开修改标识 | |||
| reConnect(ws); //连接错误 需要重连 | |||
| }; | |||
| return websock; | |||
| } | |||
| // 实际调用的方法 | |||
| function sendSock(agentData, callback) { | |||
| globalCallback = callback; | |||
| // console.log(globalCallback) | |||
| if (websock.readyState === websock.OPEN) { | |||
| // 若是ws开启状态 | |||
| websocketsend(agentData); | |||
| } else if (websock.readyState === websock.CONNECTING) { | |||
| // 若是 正在开启状态,则等待1s后重新调用 | |||
| setTimeout(function() { | |||
| sendSock(agentData, callback); | |||
| }, 1000); | |||
| } else { | |||
| // 若未开启 ,则等待1s后重新调用 | |||
| setTimeout(function() { | |||
| sendSock(agentData, callback); | |||
| }, 1000); | |||
| } | |||
| } | |||
| function getSock(callback) { | |||
| globalCallback = callback; | |||
| } | |||
| // 数据接收 | |||
| function websocketonmessage(e) { | |||
| console.log(e.data); | |||
| let O_o = JSON.parse(decodeUnicode(e.data)); | |||
| if (!O_o) { | |||
| heartCheck.reset(); | |||
| } else { | |||
| if (O_o.msg == "open success") { | |||
| sessionStorage.setItem("wid", O_o.wid); | |||
| } else { | |||
| console.log(O_o); | |||
| globalCallback(O_o); | |||
| } | |||
| } | |||
| // globalCallback(JSON.parse(e.data)) | |||
| function decodeUnicode(str) { | |||
| str = str.replace(/\\/g, "%"); | |||
| //转换中文 | |||
| str = unescape(str); | |||
| //将其他受影响的转换回原来 | |||
| str = str.replace(/%/g, "\\"); | |||
| //对网址的链接进行处理 | |||
| str = str.replace(/\\/g, ""); | |||
| return str; | |||
| } | |||
| } | |||
| // 数据发送 | |||
| function websocketsend(agentData) { | |||
| console.log(JSON.stringify(agentData)); | |||
| websock.send(JSON.stringify(agentData)); | |||
| } | |||
| // 关闭 | |||
| function websocketclose(e) { | |||
| console.log(e); | |||
| isConnect = false; //断开后修改标识 | |||
| console.log("connection closed (" + e.code + ")"); | |||
| let url = e.currentTarget.url; | |||
| reConnect(url); | |||
| } | |||
| // 创建 websocket 连接 | |||
| function websocketOpen(e) { | |||
| isConnect = true; | |||
| console.log("连接成功"); | |||
| } | |||
| // initWebSocket(); | |||
| // 将方法暴露出去 | |||
| export { initWebSocket, sendSock, getSock, createWebSocket, closeWebSocket }; | |||
| @@ -0,0 +1,134 @@ | |||
| import axios from "axios"; | |||
| import Cloudia from "../api/cloudia-sdk-v1.4.1"; | |||
| import Vue from "vue"; | |||
| let retry = 2; | |||
| let retryDelay = 1000; | |||
| class AxiosRequest { | |||
| constructor(baseUrl, isDebuggable) { | |||
| this.isDebuggable = isDebuggable; | |||
| this.instance = axios.create({ | |||
| baseURL: baseUrl, | |||
| timeout: 10000, // 10s as default | |||
| withCredentials: true, | |||
| headers: { | |||
| "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" | |||
| } | |||
| }); | |||
| this.interceptors(); | |||
| } | |||
| get(url, params) { | |||
| return this.request({ | |||
| method: "get", | |||
| url: url, | |||
| params: params | |||
| }); | |||
| } | |||
| post(url, params) { | |||
| return this.request({ | |||
| method: "post", | |||
| url: url, | |||
| headers: { | |||
| "Content-Type": "application/json;charset=UTF-8" | |||
| }, | |||
| data: params | |||
| }); | |||
| } | |||
| postForm(url, params) { | |||
| return this.request({ | |||
| method: "post", | |||
| url: url, | |||
| data: params, | |||
| transformRequest: [ | |||
| function(data) { | |||
| let ret = ""; | |||
| for (const it in data) { | |||
| ret += encodeURIComponent(it) + "=" + encodeURIComponent(data[it]) + "&"; | |||
| } | |||
| return ret; | |||
| } | |||
| ] | |||
| }); | |||
| } | |||
| postFile(url, params) { | |||
| return this.request({ | |||
| method: "post", | |||
| url: url, | |||
| headers: { | |||
| "Content-Type": "multipart/form-data" | |||
| }, | |||
| data: params, | |||
| transformRequest: [ | |||
| function(data) { | |||
| const formData = new FormData(); | |||
| for (const item in data) { | |||
| formData.append(item, data[item]); | |||
| } | |||
| return formData; | |||
| } | |||
| ] | |||
| }); | |||
| } | |||
| request(options) { | |||
| return this.instance(options); | |||
| } | |||
| interceptors() { | |||
| let that = this; | |||
| this.instance.interceptors.response.use( | |||
| (res) => { | |||
| const { data, status } = res; | |||
| if (status > 200 && status < 400) { | |||
| if (this.isDebuggable) { | |||
| Cloudia.showToast(`http code: ${status}`); | |||
| } | |||
| } else if (status !== 200) { | |||
| if (this.isDebuggable) { | |||
| Cloudia.showToast(`http code: ${status}`); | |||
| } else { | |||
| console.error(`http error, code: ${status}`); | |||
| Cloudia.showToast("请检查网络连接是否正常,稍后重试!"); | |||
| } | |||
| } | |||
| if (data.resultInfo && data.resultInfo.resultCode !== "200") { | |||
| Cloudia.showToast(`request error: ${data.resultInfo.resultMsg} (${data.resultInfo.resultCode})`); | |||
| } | |||
| return data; | |||
| }, | |||
| (error) => { | |||
| Cloudia.showToast("请检查网络连接是否正常,稍后重试!"); | |||
| console.error("网络加载失败"); | |||
| var config = error.config; | |||
| config.__retryCount = config.__retryCount || 0; | |||
| if (config.__retryCount >= retry) { | |||
| console.error("网络请求重试结束:" + config.__retryCount); | |||
| Vue.prototype.hideLoading(); | |||
| // Reject with the error | |||
| return Promise.reject(error); | |||
| } | |||
| // Increase the retry count | |||
| config.__retryCount += 1; | |||
| console.error("网络请求开始重试:" + config.__retryCount); | |||
| // Create new promise to handle exponential backoff | |||
| return new Promise(function(resolve) { | |||
| setTimeout(function() { | |||
| resolve(); | |||
| }, retryDelay); | |||
| }).then(function() { | |||
| return that.request(config); | |||
| }); | |||
| } | |||
| ); | |||
| } | |||
| } | |||
| export default AxiosRequest; | |||
| @@ -0,0 +1,41 @@ | |||
| import request from "./request"; | |||
| // https://{host-name}/api/apilist?api=Weather | |||
| // location - 城市 | |||
| // startTime - 2019-05-09/2019-05-09 12:00 | |||
| // endTime - 2019-05-12/2019-05-12 12:00 | |||
| // lang - Optional, en/cn/jp | |||
| export const getWeatherDaily = (location, startTime, endTime, lang = "cn") => { | |||
| console.info( | |||
| "request corsapi/weather?api=Weather, params:location=" + | |||
| location + | |||
| ", startTime=" + | |||
| startTime + | |||
| ", endTime=" + | |||
| endTime + | |||
| ", lang=" + | |||
| lang | |||
| ); | |||
| return request.get("corsapi/weather?api=WeatherNow", { | |||
| location: location, | |||
| lang: lang | |||
| }); | |||
| }; | |||
| export const getWeatherWeekly = (location, startTime, endTime, lang = "cn") => { | |||
| console.info( | |||
| "request corsapi/weather?api=Weather, params:location=" + | |||
| location + | |||
| ", startTime=" + | |||
| startTime + | |||
| ", endTime=" + | |||
| endTime + | |||
| ", lang=" + | |||
| lang | |||
| ); | |||
| return request.get("corsapi/weather?api=Weather", { | |||
| location: location, | |||
| startTime: startTime, | |||
| endTime: endTime, | |||
| lang: lang | |||
| }); | |||
| }; | |||
| @@ -0,0 +1,5 @@ | |||
| import AxiosRequest from "./axios"; | |||
| import config from "@/config"; | |||
| const request = new AxiosRequest(config.baseUrl, config.isDebuggable); | |||
| export default request; | |||
| @@ -0,0 +1,87 @@ | |||
| const { add, query } = require("../db/dbHelp"); | |||
| const express = require("express"); | |||
| const router = express.Router(); | |||
| // 连接数据库 | |||
| const jsonWrite = function(res, ret) { | |||
| if (typeof ret === "undefined") { | |||
| res.json({ | |||
| code: "1", | |||
| msg: "操作失败" | |||
| }); | |||
| } else { | |||
| res.json(ret); | |||
| } | |||
| }; | |||
| // 接口:增加信息sql,编辑修改信息sql1 | |||
| router.post("/save", (req, res) => { | |||
| const params = req.body; | |||
| console.log(params); | |||
| add(params, (result) => { | |||
| jsonWrite(res, result); | |||
| }); | |||
| }); | |||
| // 接口:用户管理分页接口查询 | |||
| router.get("/getlist", (req, res) => { | |||
| const params = req.body; | |||
| console.log(params); | |||
| query((result) => { | |||
| jsonWrite(res, result); | |||
| }); | |||
| }); | |||
| const db = require("../db/mssql"); //注意改路径 | |||
| router.get("/ms/detailMD", (req, res) => { | |||
| console.log(db.sql); | |||
| //根据时间查询的模板 | |||
| var count = 0; | |||
| var commonResult = []; | |||
| db.sql( | |||
| "SELECT PassType,count(1) as Count FROM HJ_PersonRecognition WHERE DateDiff(dd,DetectTime,getdate())=0 group by PassType order by PassType", | |||
| function(err, result) { | |||
| if (err) { | |||
| console.log(err); | |||
| return; | |||
| } | |||
| commonResult.push(...result.recordset); | |||
| count++; | |||
| if (count >= 3) { | |||
| res.send(commonResult); | |||
| } | |||
| } | |||
| ); | |||
| db.sql( | |||
| "select 0 as Reserve1, count(1) as cnt from HJ_PersonRecognition as person where person.Reserve1 = '0' and DATEDIFF(DAY, person.DetectTime, GETDATE()) = 0 union select 1 as Reserve1, count(1) as cnt from HJ_PersonRecognition as person where person.Reserve1 = '1' and DATEDIFF(DAY, person.DetectTime, GETDATE()) = 0", | |||
| function(err, result) { | |||
| if (err) { | |||
| console.log(err); | |||
| return; | |||
| } | |||
| commonResult.push(...result.recordset); | |||
| count++; | |||
| if (count >= 3) { | |||
| res.send(commonResult); | |||
| } | |||
| } | |||
| ); | |||
| db.sql( | |||
| "SELECT 0 as online, count(1) as num FROM HJ_EquipInfo WHERE Status = 1 and EquipTypeID = 3 union SELECT 1 as online, count(1) as num FROM HJ_EquipInfo WHERE (Status = 0 or Status = 2) and EquipTypeID = 3", | |||
| function(err, result) { | |||
| if (err) { | |||
| console.log(err); | |||
| return; | |||
| } | |||
| commonResult.push(...result.recordset); | |||
| count++; | |||
| if (count >= 3) { | |||
| res.send(commonResult); | |||
| } | |||
| } | |||
| ); | |||
| }); | |||
| module.exports = router; | |||
| @@ -0,0 +1,21 @@ | |||
| import Vue from "vue"; | |||
| import VueRouter from "vue-router"; | |||
| import ApiDemo from "../views/ApiDemo"; | |||
| Vue.use(VueRouter); | |||
| const routes = [ | |||
| { | |||
| path: "/", | |||
| name: "ApiDemo", | |||
| component: ApiDemo | |||
| } | |||
| ]; | |||
| const router = new VueRouter({ | |||
| mode: "history", | |||
| base: process.env.BASE_URL, | |||
| routes | |||
| }); | |||
| export default router; | |||
| @@ -0,0 +1,42 @@ | |||
| const ws = require("nodejs-websocket"); | |||
| console.log("开始建立连接..."); | |||
| const socket = ws | |||
| .createServer(function(conn) { | |||
| let msg = { id: "211", times: 0, name: "王武", tag: "" }; | |||
| let intval = setInterval(() => { | |||
| if (conn.readyState == 1) { | |||
| conn.sendText(JSON.stringify(msg)); | |||
| } else { | |||
| clearInterval(intval); | |||
| } | |||
| }, 2000); | |||
| conn.on("text", function(str) { | |||
| /* console.log("message:" + str); | |||
| let msg = { data: { on: 1, face: "hhhh" } }; | |||
| // let msg = "你好,这里是是日前端~"; | |||
| // let msg = 'websocket处于正常状态' | |||
| setInterval(() => { | |||
| conn.sendText(JSON.stringify(msg)); | |||
| }, 3000);*/ | |||
| }); | |||
| conn.on("connect", function(code) { | |||
| let msg = { data: { on: 1, face: "hhhh" } }; | |||
| // let msg = "你好,这里是是日前端~"; | |||
| // let msg = 'websocket处于正常状态' | |||
| setInterval(() => { | |||
| conn.sendText(JSON.stringify(msg)); | |||
| }, 3000); | |||
| }); | |||
| conn.on("close", function(code, reason) { | |||
| console.log("关闭连接"); | |||
| }); | |||
| conn.on("error", function(code, reason) { | |||
| console.log("异常关闭", code, reason); | |||
| }); | |||
| }) | |||
| .listen(8666); | |||
| console.log("WebSocket建立完毕"); | |||
| module.exports = socket; | |||
| @@ -0,0 +1,28 @@ | |||
| // node 后端服务器 | |||
| const dbRouter = require("../router/dbRouter"); | |||
| const bodyParser = require("body-parser"); | |||
| const express = require("express"); | |||
| const app = express(); | |||
| //采用设置所有均可访问的方法解决跨域问题 | |||
| app.all("*", function(req, res, next) { | |||
| //设置允许跨域的域名,*代表允许任意域名跨域 | |||
| res.header("Access-Control-Allow-Origin", "*"); | |||
| //允许的header类型 | |||
| res.header("Access-Control-Allow-Headers", "content-type"); | |||
| //跨域允许的请求方式 | |||
| res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS"); | |||
| if (req.method.toLowerCase() == "options") res.send(200); | |||
| //让options尝试请求快速结束 | |||
| else next(); | |||
| }); | |||
| // 以json格式返回出去 | |||
| app.use(bodyParser.json()); | |||
| app.use(bodyParser.urlencoded({ extended: false })); | |||
| // 后端api路由 | |||
| app.use("/api/db", dbRouter); | |||
| // 监听端口 | |||
| app.listen(13000); | |||
| console.log("success listen at port:13000......"); | |||
| @@ -0,0 +1,24 @@ | |||
| $base-width: 540; | |||
| $base-height: 976; | |||
| $border-radius: 4px; | |||
| @function vw($px) { | |||
| @return $px / $base-width * 100vw; | |||
| } | |||
| @function vh($px) { | |||
| @return $px / $base-height * 100vh; | |||
| } | |||
| @function vmax($px) { | |||
| @return $px / $base-height * 100vh; | |||
| } | |||
| @function vmin($px) { | |||
| @return $px / $base-width * 100vw; | |||
| } | |||
| @function rem($px) { | |||
| @return $px / $base-width * 100vw; | |||
| } | |||
| @@ -0,0 +1,172 @@ | |||
| import Config from "../config"; | |||
| import axios from "axios"; | |||
| import { encrypt } from "./jsencrypt"; | |||
| export const genRyts = (callback, err) => { | |||
| axios | |||
| .get(Config.serverDb + "/api/db/ms/detailMD", {}) | |||
| .then((res3) => { | |||
| var result = res3.data; | |||
| var inNum = 0; | |||
| var outNum = 0; | |||
| var faceNum = 0; | |||
| var cardNum = 0; | |||
| var onlineNum = 0; | |||
| var offlineNum = 0; | |||
| for (var item in result) { | |||
| if (result[item]["online"] && result[item]["online"] == 0) { | |||
| onlineNum = result[item]["num"]; | |||
| } else if (result[item]["online"] && result[item]["online"] == 1) { | |||
| offlineNum = result[item]["num"]; | |||
| } else if (result[item]["Reserve1"] && result[item]["Reserve1"] == 0) { | |||
| inNum = result[item]["cnt"]; | |||
| } else if (result[item]["Reserve1"] && result[item]["Reserve1"] == 1) { | |||
| outNum = result[item]["cnt"]; | |||
| } else if (result[item]["PassType"] && result[item]["PassType"] == 0) { | |||
| cardNum = result[item]["Count"]; | |||
| } else if (result[item]["PassType"] && result[item]["PassType"] == 1) { | |||
| faceNum = result[item]["Count"]; | |||
| } | |||
| } | |||
| /* var str = | |||
| "现在为您展示的是人员态势,当前20楼内总人数" + | |||
| (inNum - outNum) + | |||
| "人,通过首层大堂闸机通行人数" + | |||
| (inNum + outNum) + | |||
| "人,其中人脸识别" + | |||
| faceNum + | |||
| "人,刷卡识别" + | |||
| cardNum + | |||
| "人。";*/ | |||
| var str = "已为您打开人员态势"; | |||
| //人脸识别面板机、门禁闸机" + | |||
| // onlineNum + | |||
| // "台在线,在线率100%。 | |||
| callback(str); | |||
| }) | |||
| .catch((res) => { | |||
| err(res); | |||
| }); | |||
| }; | |||
| export const genPreRemoteReq = (obj, callback, errCallback) => { | |||
| var myHeaders = new Headers(); | |||
| myHeaders.append("Content-Type", "application/json"); | |||
| myHeaders.append("Cookie", "ASP.NET_SessionId="); | |||
| var raw = JSON.stringify({ | |||
| username: "adminadmin", | |||
| userpwd: | |||
| "Og4mnsq5AsZc+RfESX8eC9QS2aa9vEDC8Tp7c8S2ZY+d/BuNeEMoFc5Y9ycMhwWQ/gMsAWPsRaGgAvUt09WzOkdWYzlImrZrLfqa4/B26m7TtAigun5tNHCbpEb/ojjlGNmH4tQbszPwMfV6QFgYj6gAecVPYZQXOt7hdjEHdSQ=", | |||
| verificationCode: 2222 | |||
| }); | |||
| var requestOptions = { | |||
| method: "POST", | |||
| headers: myHeaders, | |||
| body: raw, | |||
| redirect: "follow" | |||
| }; | |||
| // fetch("http://192.168.1.254:8089/api/server/getkey_pc", requestOptions) | |||
| fetch("/getKey", requestOptions) | |||
| .then((response) => response.text()) | |||
| .then((res1) => { | |||
| console.log(res1); | |||
| res1 = JSON.parse(res1); | |||
| console.log(res1); | |||
| let resData = res1.HttpData.data; | |||
| var myHeaders = new Headers(); | |||
| myHeaders.append("Authorization", resData.appkey + "-" + resData.infokey); | |||
| myHeaders.append("Referer", Config.serverHj); | |||
| myHeaders.append("Content-Type", "application/json"); | |||
| myHeaders.append("Cookie", "ASP.NET_SessionId="); | |||
| var raw = JSON.stringify({ | |||
| data: obj.data | |||
| }); | |||
| var requestOptions = { | |||
| method: "POST", | |||
| headers: myHeaders, | |||
| body: raw, | |||
| redirect: "follow" | |||
| }; | |||
| // fetch(Config.serverPot + obj.path + "?_r=" + Math.random(), requestOptions) | |||
| fetch("/hj" + obj.path + "?_r=" + Math.random(), requestOptions) | |||
| // fetch("http://192.168.1.254:8088" + obj.path + "?_r=" + Math.random(), requestOptions) | |||
| .then((response) => response.text()) | |||
| .then((result) => { | |||
| console.log(result); | |||
| result = JSON.parse(result); | |||
| console.log(result); | |||
| callback(result); | |||
| }) | |||
| .catch((error) => { | |||
| console.log("error", error); | |||
| errCallback(error); | |||
| }); | |||
| }) | |||
| .catch((error) => console.log("error", error)); | |||
| /*axios | |||
| .post("http://192.168.1.254:8089/api/server/getkey_pc", { | |||
| // .post("/getKey", { | |||
| username: Config.username, | |||
| userpwd: encrypt(Config.userpwd), | |||
| verificationCode: "2222" | |||
| }) | |||
| .then((res1) => { | |||
| let resData = res1.data.HttpData.data; | |||
| var myHeaders = new Headers(); | |||
| myHeaders.append("Authorization", resData.appkey + "-" + resData.infokey); | |||
| myHeaders.append("Referer", Config.serverHj); | |||
| myHeaders.append("Content-Type", "application/json"); | |||
| myHeaders.append("Cookie", "ASP.NET_SessionId="); | |||
| var raw = JSON.stringify({ | |||
| data: obj.data | |||
| }); | |||
| var requestOptions = { | |||
| method: "POST", | |||
| headers: myHeaders, | |||
| body: raw, | |||
| redirect: "follow" | |||
| }; | |||
| // fetch(Config.serverPot + obj.path + "?_r=" + Math.random(), requestOptions) | |||
| fetch("http://192.168.1.254:8088" + obj.path + "?_r=" + Math.random(), requestOptions) | |||
| .then((response) => response.text()) | |||
| .then((result) => { | |||
| console.log(result); | |||
| result = JSON.parse(result); | |||
| console.log(result); | |||
| callback(result); | |||
| }) | |||
| .catch((error) => { | |||
| console.log("error", error); | |||
| errCallback(error); | |||
| }); | |||
| }) | |||
| .catch((res) => { | |||
| errCallback(res); | |||
| });*/ | |||
| }; | |||
| export const genRemoteReq = (resData, obj, callback, errCallback) => { | |||
| axios | |||
| .post(Config.serverHj + "/api/real/setup_service", obj, { | |||
| headers: { Authorization: resData.appkey + "-" + resData.infokey } | |||
| }) | |||
| .then(() => { | |||
| callback(); | |||
| }) | |||
| .catch((res) => { | |||
| errCallback(res); | |||
| }); | |||
| }; | |||