├── .npmignore ├── .gitignore ├── images └── weibo.png ├── src ├── assets │ └── logo.png ├── app.ux ├── pages │ ├── Home │ │ └── index.ux │ ├── About │ │ └── index.ux │ ├── Gallery │ │ └── index.ux │ └── Weibo │ │ └── index.ux ├── components │ ├── weiboUser.ux │ ├── topButton.ux │ ├── weiboBar.ux │ ├── weiboGallery.ux │ └── richContent.ux ├── manifest.json └── utils │ ├── weibo.js │ └── mv.js ├── .babelrc ├── .prettierrc ├── .editorconfig ├── .npmrc ├── README.md ├── .eslintrc.json ├── LICENSE ├── sign └── debug │ ├── certificate.pem │ └── private.pem └── package.json /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | build/ -------------------------------------------------------------------------------- /images/weibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileSmith/quickapp-weibo/HEAD/images/weibo.png -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileSmith/quickapp-weibo/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "stage-2" 5 | ], 6 | "plugins": [ 7 | "transform-runtime" 8 | ] 9 | } -------------------------------------------------------------------------------- /src/app.ux: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true, 6 | "arrowParens": "always", 7 | "trailingComma": "all" 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npm.taobao.org 2 | disturl=https://npm.taobao.org/dist 3 | chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver 4 | operadriver_cdnurl=http://cdn.npm.taobao.org/dist/operadriver 5 | phantomjs_cdnurl=http://cdn.npm.taobao.org/dist/phantomjs 6 | fse_binary_host_mirror=https://npm.taobao.org/mirrors/fsevents 7 | sass_binary_site=http://cdn.npm.taobao.org/dist/node-sass 8 | electron_mirror=http://cdn.npm.taobao.org/dist/electron/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # quickapp-weibo 2 | 3 | 简单的热门微博展示,用于体验快应用的开发过程和性能分析。整体思路参考另一个 [小程序Demo](https://github.com/SmileSmith/miniweibo) 4 | 5 | ##### 开发中,如有问题请指导和拍砖 ~ ~** 6 | 7 | 8 | 效果预览: 9 | 10 | ![](images/weibo.png)! 11 | 12 | ## Before 13 | 14 | #### 1. 安装快应用toolkit 15 | 16 | `npm i -g hap-toolkit` 17 | 18 | #### 2. 手机安装调试器和快应用启动器、并保证和电脑同局域网 19 | 20 | 下载地址:https://www.quickapp.cn/docCenter/post/69 21 | 22 | #### 3. 安装项目依赖 23 | 24 | `npm i install` 25 | 26 | ## Start 27 | 28 | #### 1. 启动rpk-server,充当远程代码分发者;开启代码实时编译 29 | 30 | `npm run server` 31 | `npm run watch` 32 | 33 | #### 2. 手机打开调试器,扫码; 34 | 35 | #### 3. 如提示安装失败,检查电脑IP,有时扫码IP会不正确 36 | 37 | ## Update Log 38 | 39 | ## Roadmap 40 | 41 | + 1、全局状态管理 42 | 43 | + 2、类型检测 44 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "commonjs": true, 4 | "es6": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "parser": "babel-eslint", 8 | "parserOptions": { 9 | "sourceType": "module", 10 | "ecmaFeatures": { 11 | "experimentalObjectRestSpread": true, 12 | "jsx": true 13 | } 14 | }, 15 | "globals": { 16 | "loadData": false, 17 | "saveData": false, 18 | "history": false, 19 | "console": false, 20 | "setTimeout": false, 21 | "clearTimeout": false, 22 | "setInterval": false, 23 | "clearInterval": false 24 | }, 25 | "plugins": ["hybrid"], 26 | "rules": { 27 | "indent": ["warn", 2, { "SwitchCase": 1 }], 28 | "no-console": ["warn", { "allow": ["info", "warn", "error"] }], 29 | "no-unused-vars": ["warn", { "varsIgnorePattern": "prompt" }], 30 | "quotes": ["warn", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], 31 | "linebreak-style": "off", 32 | "semi": ["warn", "always"] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/pages/Home/index.ux: -------------------------------------------------------------------------------- 1 | 9 | 10 | 33 | 34 | 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Smile 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/weiboUser.ux: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | 53 | -------------------------------------------------------------------------------- /src/components/topButton.ux: -------------------------------------------------------------------------------- 1 | 7 | 15 | 16 | 51 | -------------------------------------------------------------------------------- /src/components/weiboBar.ux: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 49 | -------------------------------------------------------------------------------- /sign/debug/certificate.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDMTCCAhmgAwIBAgIJAMKpjyszxkDpMA0GCSqGSIb3DQEBCwUAMC4xCzAJBgNV 3 | BAYTAkNOMQwwCgYDVQQKDANSUEsxETAPBgNVBAMMCFJQS0RlYnVnMCAXDTE3MDQx 4 | OTAyMzE0OVoYDzIxMTYwMzI2MDIzMTQ5WjAuMQswCQYDVQQGEwJDTjEMMAoGA1UE 5 | CgwDUlBLMREwDwYDVQQDDAhSUEtEZWJ1ZzCCASIwDQYJKoZIhvcNAQEBBQADggEP 6 | ADCCAQoCggEBAK3kPd9jzvTctTIA3XNZVv9cHHDbAc6nTBfdZp9mtPOTkXFpvyCb 7 | kL0QjOog0+1pv8D7dFeP4ptWXU5CT3ImvaPR+16dAtMRcsxEr5q4zieJzx3O6huL 8 | UBa1k+xrzjXpRzkcOysmc8fTxt0tAwbDgJ2AA5TlXLTcVyb7GmJ+hl5CjnhoG5NN 9 | LrkqI7S29c1U3uokj8Q7hzaj0TURu/uB5ZIMCLZY9KFDugqaEcvmUyJiD0fuV6sA 10 | O/4kpiZUOnhV8/xWpRbMI4WFQsfgLOCV+X9uzUa29D677y//46t/EDSuQTHyBZbl 11 | AcNMENkpMWZsH7J/+F19+U0/Hd5bJgneVRkCAwEAAaNQME4wHQYDVR0OBBYEFKDN 12 | SZtt47ttOBDQzIchFYyxsg3mMB8GA1UdIwQYMBaAFKDNSZtt47ttOBDQzIchFYyx 13 | sg3mMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABaZctNrn4gLmNf/ 14 | eNJ3x5CJIPjPwm6j9nwKhtadJ6BF+TIzSkJuHSgxULjW436F37otv94NPzT5PCBF 15 | WxgXoqgLqnWwvsaqC4LUEjsZviWW4CB824YDUquEUVGFLE/U5KTZ7Kh1ceyUk4N8 16 | +mtkXkanWoBBk0OF24lNrAsNLB63yTLr9HxEe75+kmvxf1qVJUGtaOEWIhiFMiAB 17 | 5D4w/j2EFWktumjuy5TTwU0zhl52bc8V9SNixM1IaqzNrVPrdjv8viUX548pU3WT 18 | xZ5ylDsxhMC1q4BXQVeIY8C0cMEX+WHOmOCvWrkxCkP91pKsSPkuVrWlzrkn8Ojo 19 | swP6sBw= 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.smilesmith.eyes", 3 | "name": "观止于此", 4 | "versionName": "1.0.0", 5 | "versionCode": "1", 6 | "minPlatformVersion": "101", 7 | "icon": "/assets/logo.png", 8 | "features": [ 9 | { "name": "system.prompt" }, 10 | { "name": "system.router" }, 11 | { "name": "system.shortcut" }, 12 | { "name": "system.storage" }, 13 | { "name": "system.fetch" }, 14 | { "name": "system.webview" } 15 | ], 16 | "permissions": [{ "origin": "*" }], 17 | "config": { 18 | "logLevel": "info", 19 | "designWidth": 375 20 | }, 21 | "router": { 22 | "entry": "pages/Home", 23 | "pages": { 24 | "pages/Home": { 25 | "component": "index" 26 | }, 27 | "pages/Weibo": { 28 | "component": "index" 29 | }, 30 | "pages/About": { 31 | "component": "index" 32 | }, 33 | "pages/Gallery": { 34 | "component": "index" 35 | } 36 | } 37 | }, 38 | "display": { 39 | "titleBarBackgroundColor": "#e6162d", 40 | "titleBarTextColor": "#eeeeee", 41 | "menu": true, 42 | "pages": { 43 | "pages/Home": { 44 | "titleBarText": "主页", 45 | "menu": false 46 | }, 47 | "pages/Weibo": { 48 | "titleBarText": "热门微博" 49 | }, 50 | "pages/About": { 51 | "titleBarText": "关于" 52 | }, 53 | "pages/Gallery": { 54 | "fullScreen": true, 55 | "menu": false, 56 | "titleBar": false, 57 | "backgroundColor": "#666666" 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/components/weiboGallery.ux: -------------------------------------------------------------------------------- 1 | 14 | 15 | 37 | 38 | 51 | -------------------------------------------------------------------------------- /sign/debug/private.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCt5D3fY8703LUy 3 | AN1zWVb/XBxw2wHOp0wX3WafZrTzk5Fxab8gm5C9EIzqINPtab/A+3RXj+KbVl1O 4 | Qk9yJr2j0ftenQLTEXLMRK+auM4nic8dzuobi1AWtZPsa8416Uc5HDsrJnPH08bd 5 | LQMGw4CdgAOU5Vy03Fcm+xpifoZeQo54aBuTTS65KiO0tvXNVN7qJI/EO4c2o9E1 6 | Ebv7geWSDAi2WPShQ7oKmhHL5lMiYg9H7lerADv+JKYmVDp4VfP8VqUWzCOFhULH 7 | 4Czglfl/bs1GtvQ+u+8v/+OrfxA0rkEx8gWW5QHDTBDZKTFmbB+yf/hdfflNPx3e 8 | WyYJ3lUZAgMBAAECggEBAJTnCBBdUB+fSs1prjeS/gsmnfgJoY+K9H7PCIxgj3yw 9 | FXAvZAmRDKzJGlF2EOOQlTG0YNiGDj6EAtv7rjoKcINyULSg8IU6wLmn61MrAuUa 10 | fa+Bujgh4E/B5swhOHAztNhzkzsM70Hi17wXSislh+HWd7qteOgqcbqgdOR4gaj+ 11 | HUqtcxG3H3hCL3dWugnjLZMtestLKGHSSZvbQNjYM3kKy2LvO8NpxmDE4a+TXygK 12 | qhaZjmS/dc/nJBJzOfkzby58RvGbzlJflfW/Uu3/gizj13GFQKWonq1xh630RAhv 13 | xX5ySok2aAx/+/SiJSpNXvM09grQuoORSr7D1tm+5rECgYEA3vf0hRfua0XAOu6f 14 | pyzNvLRRJ/pEew7XpNPCyS2TuMTd1yvXjGVxQfP46N6x1IM3SRU0zE+LSk80EF7l 15 | u1Or7GyCEhabYNe/7P2F8ENP73Do0HwvcI1jGrgr6r9oK0J27Xei+f6Q0bgJOPI2 16 | qaLj+V37cOjkNSM1mhTjtDwK8k0CgYEAx6cMrkjHl1+lDIIOc3qAEL3jb3xQveYk 17 | WrMF/B+j048k6boU4VvFJAIyQxOxMNxLjw3/9+zXCFJT4WaZK3TMXlg614ASGx3H 18 | tKjJM9O07ywwMq1gbutFS4nHCg3L3Os6esL0SPwMdATR3Yh22n5OGI9o+/aURulL 19 | GPEXef1Z2/0CgYEAgmwp5LxV4vu+8Pnp+4DSq4ISQr861XyeGTUhKEp3sUm+tgFY 20 | KTChakHKpHS3Mqa6bQ5xft08je/8dWL9IHFWDIqAHxKIOsKY6oh1k0/cbyPtmx45 21 | Ja4efV+jmMHzrfJH3KnxdCg7D+GFy4CrBtlYXuJhlO81pft9fC6h7yh8ArUCgYBq 22 | gvkl5Zftbs4rnRq+iqTVyagTKvwcQzIz3PwdZHfO/rfPpUFMdNv4eN99n3zRN0Vs 23 | HSjoiEazntA3GLgwUdBRqLpDi4SdSMbo337vkksdqbJQ5uPiaMuAIBG6kF+pDSkW 24 | ovkWErlGD+gySoI10FozihaVDRhPuFgjB0PiBcIxtQKBgGNSzX+Bx5+ux1Qny0Sn 25 | SUcBtepLnO8M8wafoGNyehbMnLzfuMbaDiJOdozGlBNHZTtPB3r4AYb8WnltdKW0 26 | 7i3fk26YZGiMVeUJvewA6/LOBEaqMdwoNwnoptvbR6ehHeE/PPtRtge2cD3bPIM7 27 | U9VlWgfgj9Dxfwhslqb9hmyp 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /src/components/richContent.ux: -------------------------------------------------------------------------------- 1 | 9 | 10 | 63 | 64 | 82 | -------------------------------------------------------------------------------- /src/utils/weibo.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 过滤cookie 4 | * 5 | * @param {any} cookie 6 | * @returns 7 | */ 8 | export function getCookieFilter(cookie) { 9 | return cookie.replace(/,([^ ])/g, '; $1') 10 | .replace(/( expires| Max-Age| domain| path| HttpOnly)=?.*?;/g, '') 11 | .replace(/; HttpOnly$/, ''); 12 | } 13 | 14 | /** 15 | * 过滤微博中的富文本 16 | * 17 | * @param {any} text 18 | * @returns 19 | */ 20 | function getTextFilter(text) { 21 | return text 22 | // .replace(/https?:\/\/[\w\d./]+/g, '[网页链接]') 23 | .replace(//g, '\n') 24 | .replace(/"/g, '"') 25 | .replace(/>/g, '>') 26 | .replace(/</g, '<') 27 | .replace(/&/g, '&'); 28 | } 29 | 30 | /** 31 | * 过滤有效的微博信息 32 | * 33 | * @param {any} weibo 34 | * @returns 35 | */ 36 | export function getWeiboInfo(weibo) { 37 | // 时间和来源 38 | const createdAt = weibo.created_at || '宇宙大爆炸前'; 39 | const source = weibo.source || '火星'; 40 | 41 | // 图片 42 | const pics = { 43 | smalls: weibo.pics ? weibo.pics.map(pic => pic.url) : [], 44 | larges: weibo.pics ? weibo.pics.map(pic => pic.large.url) : [], 45 | }; 46 | 47 | let text = weibo.text || '这里一片荒芜...'; 48 | 49 | let video = null; 50 | // 读取页面和多媒体信息 51 | if (weibo.page_info) { 52 | const page = weibo.page_info; 53 | if (page.type === 'video') { 54 | text = weibo.text ? weibo.text : `${page.page_title} ${page.content2}`; 55 | video = { 56 | url: page.media_info.stream_url, 57 | pic: page.page_pic.url, 58 | }; 59 | } 60 | if (!weibo.text && page.type === 'topic') { 61 | text = `${page.page_title} ${page.content1}`; 62 | } 63 | if (!weibo.text && page.type === 'webpage') { 64 | text = `${page.page_title} ${page.content2}`; 65 | } 66 | } 67 | 68 | return { 69 | id: weibo.id, 70 | user: { 71 | profile_image_url: weibo.user.profile_image_url, 72 | screen_name: weibo.user.screen_name, 73 | }, 74 | created_at: createdAt, 75 | source, 76 | pics, 77 | video, 78 | text: getTextFilter(text), 79 | bar: { 80 | attitudes: weibo.attitudes_count, 81 | comments: weibo.comments_count, 82 | reposts: weibo.reposts_count, 83 | }, 84 | }; 85 | } 86 | 87 | /** 88 | * 过滤评论数据 89 | * 90 | * @export 91 | * @param {any} comment 92 | * @returns 93 | */ 94 | export function getCommentInfo(comment) { 95 | // 时间和来源 96 | const createdAt = comment.created_at || '宇宙大爆炸前'; 97 | const source = comment.source || '火星'; 98 | const text = comment.text || '这里一片荒芜...'; 99 | 100 | return { 101 | id: comment.id, 102 | user: { 103 | profile_image_url: comment.user.profile_image_url, 104 | screen_name: comment.user.screen_name, 105 | }, 106 | created_at: createdAt, 107 | source, 108 | likes: comment.like_counts, 109 | text: getTextFilter(text), 110 | }; 111 | } 112 | 113 | export default { 114 | getWeiboInfo, 115 | getCommentInfo, 116 | getCookieFilter, 117 | }; 118 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quickApp", 3 | "version": "1.0.0", 4 | "subversion": { 5 | "toolkit": "0.0.30", 6 | "packager": "0.0.5" 7 | }, 8 | "description": "", 9 | "scripts": { 10 | "build": "cross-env NODE_PLATFORM=na NODE_PHASE=dv webpack --config ./node_modules/hap-tools/webpack.config.js", 11 | "release": "cross-env NODE_PLATFORM=na NODE_PHASE=ol webpack --config ./node_modules/hap-tools/webpack.config.js", 12 | "clear": "rm -rf build/* && rm -rf dist/*", 13 | "server": "cross-env NODE_MOUNTED_ROUTER=\"debug bundle\" node ./node_modules/hap-tools/debugger/server/index.js", 14 | "debug": "npm run server -- --debug-only --port=8081", 15 | "notify": "node ./node_modules/hap-tools/debugger/command/notify.js", 16 | "watch": "cross-env NODE_PLATFORM=na NODE_PHASE=dv webpack --config ./node_modules/hap-tools/webpack.config.js --watch", 17 | "watch:na": "npm run na:dv -- --watch", 18 | "na": "npm run na:dv -- --watch", 19 | "lint": "./node_modules/.bin/eslint src/", 20 | "na:dv": "cross-env NODE_PLATFORM=na NODE_PHASE=dv webpack --config ./node_modules/hap-tools/webpack.config.js", 21 | "na:qa": "cross-env NODE_PLATFORM=na NODE_PHASE=qa webpack --config ./node_modules/hap-tools/webpack.config.js", 22 | "na:ol": "cross-env NODE_PLATFORM=na NODE_PHASE=ol webpack --config ./node_modules/hap-tools/webpack.config.js", 23 | "postinstall": "npm run postinstall:koaStatic && npm run postinstall:koaSend", 24 | "postinstall:koaStatic": "babel -d ./node_modules/koa-static ./node_modules/koa-static", 25 | "postinstall:koaSend": "babel -d ./node_modules/koa-send ./node_modules/koa-send" 26 | }, 27 | "dependencies": { 28 | "archiver": "^1.3.0", 29 | "babel-polyfill": "^6.26.0", 30 | "babel-preset-env": "^1.6.0", 31 | "babel-preset-stage-2": "^6.22.0", 32 | "babel-plugin-transform-runtime": "^6.9.0", 33 | "babel-runtime": "^6.9.2", 34 | "babel-template": "^6.24.1", 35 | "babel-traverse": "^6.24.1", 36 | "babel-types": "^6.24.1", 37 | "babylon": "^6.17.0", 38 | "babylon-jsx": "^1.0.0", 39 | "browserify": "^13.1.1", 40 | "chalk": "^1.1.3", 41 | "css": "~2.2.1", 42 | "escodegen": "~1.7.1", 43 | "esprima": "~2.7.0", 44 | "fs-extra": "^3.0.1", 45 | "fsmonitor": "^0.2.4", 46 | "hash-sum": "^1.0.2", 47 | "loader-utils": "~0.2.14", 48 | "md5": "^2.1.0", 49 | "parse5": "^3.0.0", 50 | "prompt": "^1.0.0", 51 | "qr-image": "^3.2.0", 52 | "resolve-bin": "^0.4.0", 53 | "serve": "^3.4.0", 54 | "source-map": "^0.5.6", 55 | "xtoolkit": "^0.1.7", 56 | "yargs": "^6.6.0", 57 | "jsrsasign": "^7.1.2", 58 | "jsrsasign-util": "^1.0.0", 59 | "qrcode-terminal": "^0.11.0", 60 | "socket.io": "^2.0.3", 61 | "tar": "^3.1.5" 62 | }, 63 | "devDependencies": { 64 | "babel-cli": "^6.10.1", 65 | "babel-core": "^6.10.4", 66 | "babel-eslint": "^8.2.1", 67 | "babel-loader": "^6.2.4", 68 | "babel-plugin-syntax-jsx": "^6.18.0", 69 | "cross-env": "^3.2.4", 70 | "css-what": "^2.1.0", 71 | "eslint": "^4.3.0", 72 | "eslint-plugin-hybrid": "~0.0.1", 73 | "file-loader": "^0.9.0", 74 | "html-webpack-plugin": "^2.28.0", 75 | "hybrid-chai": "~0.0.1", 76 | "hybrid-mocha": "~0.0.1", 77 | "js-base64": "^2.1.9", 78 | "koa": "^2.3.0", 79 | "koa-body": "^2.5.0", 80 | "koa-router": "^7.2.1", 81 | "koa-send": "^4.1.1", 82 | "koa-static": "^4.0.1", 83 | "sinon": "^1.17.3", 84 | "sinon-chai": "^2.8.0", 85 | "url-loader": "^0.5.7", 86 | "webdriverio": "^4.8.0", 87 | "webpack": "~1.13.0", 88 | "webpack-dev-server": "^1.16.5" 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/pages/About/index.ux: -------------------------------------------------------------------------------- 1 | 38 | 39 | 135 | 136 | 162 | -------------------------------------------------------------------------------- /src/pages/Gallery/index.ux: -------------------------------------------------------------------------------- 1 | 15 | 16 | 58 | 59 | 139 | -------------------------------------------------------------------------------- /src/pages/Weibo/index.ux: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 36 | 37 | 130 | 131 | 172 | -------------------------------------------------------------------------------- /src/utils/mv.js: -------------------------------------------------------------------------------- 1 | import fetch from '@system.fetch'; 2 | import storage from '@system.storage'; 3 | import prompt from '@system.prompt'; 4 | import router from '@system.router'; 5 | import shortcut from '@system.shortcut'; 6 | 7 | /** 8 | * 显示菜单 9 | */ 10 | function showMenu() { 11 | var appInfo = require('@system.app').getInfo(); 12 | prompt.showContextMenu({ 13 | itemList: ['保存桌面', '关于', '取消'], 14 | success: function(ret) { 15 | switch (ret.index) { 16 | case 0: 17 | // 保存桌面 18 | createShortcut(); 19 | break; 20 | case 1: 21 | // 关于 22 | router.push({ 23 | uri: '/pages/About', 24 | params: { name: appInfo.name, icon: appInfo.icon }, 25 | }); 26 | break; 27 | case 2: 28 | // 取消 29 | break; 30 | default: 31 | prompt.showToast({ message: 'error' }); 32 | } 33 | }, 34 | }); 35 | } 36 | 37 | /** 38 | * 创建桌面图标 39 | * 注意:使用加载器测试`创建桌面快捷方式`功能时,请先在`系统设置`中打开`应用加载器`的`桌面快捷方式`权限 40 | */ 41 | function createShortcut() { 42 | shortcut.hasInstalled({ 43 | success: function(ret) { 44 | if (ret) { 45 | prompt.showToast({ message: '已创建桌面图标' }); 46 | } else { 47 | shortcut.install({ 48 | success: function() { 49 | prompt.showToast({ message: '成功创建桌面图标' }); 50 | }, 51 | fail: function(errmsg, errcode) { 52 | prompt.showToast({ message: 'error: ' + errcode + '---' + errmsg }); 53 | }, 54 | }); 55 | } 56 | }, 57 | }); 58 | } 59 | 60 | 61 | /** 62 | * 封装网络请求中的JSON.parse 63 | * 64 | * @param {any} 请求参数,含url、method、data、header等 65 | * @returns Promise 66 | */ 67 | function request(obj){ 68 | return new Promise((resolve, reject) => { 69 | fetch.fetch({ 70 | ...obj, 71 | success: (res) =>{ 72 | try { 73 | res.data = JSON.parse(res.data); 74 | resolve(res); 75 | } catch (err) { 76 | console.error(err); 77 | } 78 | }, 79 | fail: reject, 80 | }); 81 | }); 82 | } 83 | 84 | const wx = wx; 85 | 86 | // 全局mv对象 87 | const mv = {}; 88 | 89 | if (!wx) { 90 | mv.request = request; 91 | mv.setStorage = storage.set; 92 | mv.getStorage = storage.get; 93 | mv.removeStorage = storage.delete; 94 | mv.showToast = prompt.showToast; 95 | mv.showModal = prompt.showDialog; 96 | mv.navigateTo = router.push; 97 | mv.navigateBack = router.back; 98 | mv.redirectTo = router.replace; 99 | mv.showMenu = showMenu; 100 | mv.createShortcut = createShortcut; 101 | } 102 | 103 | /** 104 | * Promise转换函数 105 | * 106 | * @param {any} func 107 | * @param {any} obj 108 | * @returns 109 | */ 110 | function toPromise(func, obj) { 111 | return new Promise((resolve, reject) => { 112 | func({ 113 | ...obj, 114 | success: resolve, 115 | fail: reject, 116 | }); 117 | }); 118 | } 119 | 120 | export default { 121 | // 快应用菜单栏 122 | showMenu: mv.showMenu, 123 | // 快应用创建快捷方式 124 | createShortcut: mv.createShortcut, 125 | 126 | // 网络请求 127 | request: mv.request, 128 | // 界面交互 129 | showToast: obj => toPromise(mv.showToast, obj), 130 | // showLoading: obj => toPromise(mv.showLoading, obj), 131 | showModal: obj => toPromise(mv.showModal, obj), 132 | // showActionSheet: obj => toPromise(mv.showActionSheet, obj), 133 | // // 导航条 134 | // setNavigationBarTitle: obj => toPromise(mv.setNavigationBarTitle, obj), 135 | // setNavigationBarColor: obj => toPromise(mv.setNavigationBarColor, obj), 136 | // setTopBarText: obj => toPromise(mv.setTopBarText, obj), 137 | // // 导航 138 | navigateTo: obj => toPromise(mv.navigateTo, obj), 139 | redirectTo: obj => toPromise(mv.redirectTo, obj), 140 | // switchTab: obj => toPromise(mv.switchTab, obj), 141 | // reLaunch: obj => toPromise(mv.reLaunch, obj), 142 | navigateBack: obj => toPromise(mv.navigateBack, obj), 143 | 144 | // // 用户相关 145 | // login: obj => toPromise(mv.login, obj), 146 | // checkSession: obj => toPromise(mv.checkSession, obj), 147 | // authorize: obj => toPromise(mv.authorize, obj), 148 | // getUserInfo: obj => toPromise(mv.getUserInfo, obj), 149 | 150 | // // 支付 151 | // requestPayment: obj => toPromise(mv.requestPayment, obj), 152 | 153 | // // 图片 154 | // chooseImage: obj => toPromise(mv.chooseImage, obj), 155 | // previewImage: obj => toPromise(mv.previewImage, obj), 156 | // getImageInfo: obj => toPromise(mv.getImageInfo, obj), 157 | // saveImageToPhotosAlbum: obj => toPromise(mv.saveImageToPhotosAlbum, obj), 158 | 159 | // // 文件 160 | // uploadFile: obj => toPromise(mv.uploadFile, obj), 161 | // downloadFile: obj => toPromise(mv.downloadFile, obj), 162 | 163 | // // 录音 164 | // startRecord: obj => toPromise(mv.startRecord, obj), 165 | 166 | // // 音频播放 167 | // playVoice: obj => toPromise(mv.playVoice, obj), 168 | 169 | // // 音乐播放 170 | // getBackgroundAudioPlayerState: obj => toPromise(mv.getBackgroundAudioPlayerState, obj), 171 | // playBackgroundAudio: obj => toPromise(mv.playBackgroundAudio, obj), 172 | // seekBackgroundAudio: obj => toPromise(mv.seekBackgroundAudio, obj), 173 | 174 | // // 视频 175 | // chooseVideo: obj => toPromise(mv.chooseVideo, obj), 176 | // saveVideoToPhotosAlbum: obj => toPromise(mv.saveVideoToPhotosAlbum, obj), 177 | 178 | // // 文件 179 | // saveFile: obj => toPromise(mv.saveFile, obj), 180 | // getFileInfo: obj => toPromise(mv.getFileInfo, obj), 181 | // getSavedFileList: obj => toPromise(mv.getSavedFileList, obj), 182 | // getSavedFileInfo: obj => toPromise(mv.getSavedFileInfo, obj), 183 | // removeSavedFile: obj => toPromise(mv.removeSavedFile, obj), 184 | // openDocument: obj => toPromise(mv.openDocument, obj), 185 | 186 | // // 数据缓存 187 | setStorage: (obj) => toPromise(mv.setStorage, obj), 188 | getStorage: (obj) => toPromise(mv.getStorage, obj), 189 | // getStorageInfo: obj => toPromise(mv.getStorageInfo, obj), 190 | removeStorage: (obj) => toPromise(mv.removeStorage, obj), 191 | 192 | // // 位置 193 | // getLocation: obj => toPromise(mv.getLocation, obj), 194 | // chooseLocation: obj => toPromise(mv.chooseLocation, obj), 195 | // openLocation: obj => toPromise(mv.openLocation, obj), 196 | 197 | // // 设备 198 | // getSystemInfo: obj => toPromise(mv.getSystemInfo, obj), 199 | // getNetworkType: obj => toPromise(mv.getNetworkType, obj), 200 | // startAccelerometer: obj => toPromise(mv.startAccelerometer, obj), 201 | // stopAccelerometer: obj => toPromise(mv.stopAccelerometer, obj), 202 | // startCompass: obj => toPromise(mv.startCompass, obj), 203 | // stopCompass: obj => toPromise(mv.stopCompass, obj), 204 | // // 打电话 205 | // makePhoneCall: obj => toPromise(mv.makePhoneCall, obj), 206 | // // 扫码 207 | // scanCode: obj => toPromise(mv.scanCode, obj), 208 | // // 剪切板 209 | // setClipboardData: obj => toPromise(mv.setClipboardData, obj), 210 | // getClipboardData: obj => toPromise(mv.getClipboardData, obj), 211 | // // 蓝牙 212 | // openBluetoothAdapter: obj => toPromise(mv.openBluetoothAdapter, obj), 213 | // closeBluetoothAdapter: obj => toPromise(mv.closeBluetoothAdapter, obj), 214 | // getBluetoothAdapterState: obj => toPromise(mv.getBluetoothAdapterState, obj), 215 | // startBluetoothDevicesDiscovery: obj => toPromise(mv.startBluetoothDevicesDiscovery, obj), 216 | // stopBluetoothDevicesDiscovery: obj => toPromise(mv.stopBluetoothDevicesDiscovery, obj), 217 | // getBluetoothDevices: obj => toPromise(mv.getBluetoothDevices, obj), 218 | // getConnectedBluetoothDevices: obj => toPromise(mv.getConnectedBluetoothDevices, obj), 219 | // createBLEConnection: obj => toPromise(mv.createBLEConnection, obj), 220 | // closeBLEConnection: obj => toPromise(mv.closeBLEConnection, obj), 221 | // getBLEDeviceServices: obj => toPromise(mv.getBLEDeviceServices, obj), 222 | // // iBeacon 223 | // startBeaconDiscovery: obj => toPromise(mv.startBeaconDiscovery, obj), 224 | // stopBeaconDiscovery: obj => toPromise(mv.stopBeaconDiscovery, obj), 225 | // getBeacons: obj => toPromise(mv.getBeacons, obj), 226 | // // 屏幕亮度 227 | // setScreenBrightness: obj => toPromise(mv.setScreenBrightness, obj), 228 | // getScreenBrightness: obj => toPromise(mv.getScreenBrightness, obj), 229 | // setKeepScreenOn: obj => toPromise(mv.setKeepScreenOn, obj), 230 | // // 振动 231 | // vibrateLong: obj => toPromise(mv.vibrateLong, obj), 232 | // vibrateShort: obj => toPromise(mv.vibrateShort, obj), 233 | // // 联系人 234 | // addPhoneContact: obj => toPromise(mv.addPhoneContact, obj), 235 | // // NFC 236 | // getHCEState: obj => toPromise(mv.getHCEState, obj), 237 | // startHCE: obj => toPromise(mv.startHCE, obj), 238 | // stopHCE: obj => toPromise(mv.stopHCE, obj), 239 | // sendHCEMessage: obj => toPromise(mv.sendHCEMessage, obj), 240 | // // Wi-Fi 241 | // startWifi: obj => toPromise(mv.startWifi, obj), 242 | // stopWifi: obj => toPromise(mv.stopWifi, obj), 243 | // connectWifi: obj => toPromise(mv.connectWifi, obj), 244 | // getWifiList: obj => toPromise(mv.getWifiList, obj), 245 | // setWifiList: obj => toPromise(mv.setWifiList, obj), 246 | // getConnectedWifi: obj => toPromise(mv.getConnectedWifi, obj), 247 | 248 | // // 第三方平台 249 | // getExtConfig: obj => toPromise(mv.getExtConfig, obj), 250 | 251 | // // 转发 252 | // showShareMenu: obj => toPromise(mv.showShareMenu, obj), 253 | // hideShareMenu: obj => toPromise(mv.hideShareMenu, obj), 254 | // updateShareMenu: obj => toPromise(mv.updateShareMenu, obj), 255 | // getShareInfo: obj => toPromise(mv.getShareInfo, obj), 256 | 257 | // // 收货地址 258 | // chooseAddress: obj => toPromise(mv.chooseAddress, obj), 259 | 260 | // // 卡券 261 | // addCard: obj => toPromise(mv.addCard, obj), 262 | // openCard: obj => toPromise(mv.openCard, obj), 263 | 264 | // // 设置 265 | // openSetting: obj => toPromise(mv.openSetting, obj), 266 | // getSetting: obj => toPromise(mv.getSetting, obj), 267 | 268 | // // 微信运动 269 | // getWeRunData: obj => toPromise(mv.getWeRunData, obj), 270 | 271 | // // 打开小程序 272 | // navigateToMiniProgram: obj => toPromise(mv.navigateToMiniProgram, obj), 273 | // navigateBackMiniProgram: obj => toPromise(mv.navigateBackMiniProgram, obj), 274 | 275 | // // 获取发票抬头 276 | // chooseInvoiceTitle: obj => toPromise(mv.chooseInvoiceTitle, obj), 277 | 278 | // // 生物认证 279 | // checkIsSupportSoterAuthentication: obj => toPromise(mv.checkIsSupportSoterAuthentication, obj), 280 | // startSoterAuthentication: obj => toPromise(mv.startSoterAuthentication, obj), 281 | // checkIsSoterEnrolledInDevice: obj => toPromise(mv.checkIsSoterEnrolledInDevice, obj), 282 | }; 283 | --------------------------------------------------------------------------------