├── .editorconfig ├── .gitignore ├── README.md ├── config.xml ├── ionic.config.json ├── package-lock.json ├── package.json ├── resources ├── README.md ├── android │ ├── icon │ │ ├── drawable-hdpi-icon.png │ │ ├── drawable-ldpi-icon.png │ │ ├── drawable-mdpi-icon.png │ │ ├── drawable-xhdpi-icon.png │ │ ├── drawable-xxhdpi-icon.png │ │ └── drawable-xxxhdpi-icon.png │ └── splash │ │ ├── drawable-land-hdpi-screen.png │ │ ├── drawable-land-ldpi-screen.png │ │ ├── drawable-land-mdpi-screen.png │ │ ├── drawable-land-xhdpi-screen.png │ │ ├── drawable-land-xxhdpi-screen.png │ │ ├── drawable-land-xxxhdpi-screen.png │ │ ├── drawable-port-hdpi-screen.png │ │ ├── drawable-port-ldpi-screen.png │ │ ├── drawable-port-mdpi-screen.png │ │ ├── drawable-port-xhdpi-screen.png │ │ ├── drawable-port-xxhdpi-screen.png │ │ └── drawable-port-xxxhdpi-screen.png ├── icon.png ├── ios │ ├── icon │ │ ├── icon-1024.png │ │ ├── icon-40.png │ │ ├── icon-40@2x.png │ │ ├── icon-40@3x.png │ │ ├── icon-50.png │ │ ├── icon-50@2x.png │ │ ├── icon-60.png │ │ ├── icon-60@2x.png │ │ ├── icon-60@3x.png │ │ ├── icon-72.png │ │ ├── icon-72@2x.png │ │ ├── icon-76.png │ │ ├── icon-76@2x.png │ │ ├── icon-83.5@2x.png │ │ ├── icon-small.png │ │ ├── icon-small@2x.png │ │ ├── icon-small@3x.png │ │ ├── icon.png │ │ └── icon@2x.png │ └── splash │ │ ├── Default-568h@2x~iphone.png │ │ ├── Default-667h.png │ │ ├── Default-736h.png │ │ ├── Default-Landscape-736h.png │ │ ├── Default-Landscape@2x~ipad.png │ │ ├── Default-Landscape@~ipadpro.png │ │ ├── Default-Landscape~ipad.png │ │ ├── Default-Portrait@2x~ipad.png │ │ ├── Default-Portrait@~ipadpro.png │ │ ├── Default-Portrait~ipad.png │ │ ├── Default@2x~iphone.png │ │ ├── Default@2x~universal~anyany.png │ │ └── Default~iphone.png └── splash.png ├── src ├── app │ ├── app.component.ts │ ├── app.html │ ├── app.module.ts │ ├── app.scss │ └── main.ts ├── assets │ ├── icon │ │ └── favicon.ico │ └── imgs │ │ └── logo.png ├── core │ ├── core.module.ts │ ├── db.ts │ ├── error.ts │ ├── http.ts │ └── utils.ts ├── index.html ├── manifest.json ├── pages │ ├── about │ │ ├── about.html │ │ ├── about.scss │ │ └── about.ts │ ├── contact │ │ ├── contact.html │ │ ├── contact.scss │ │ ├── contact.ts │ │ └── mock-data.ts │ ├── echarts │ │ ├── echarts.html │ │ ├── echarts.module.ts │ │ ├── echarts.scss │ │ └── echarts.ts │ ├── home │ │ ├── home.html │ │ ├── home.scss │ │ └── home.ts │ ├── login │ │ ├── login.html │ │ ├── login.scss │ │ └── login.ts │ ├── tabs │ │ ├── tabs.html │ │ └── tabs.ts │ └── user-info │ │ ├── user-info.html │ │ ├── user-info.module.ts │ │ ├── user-info.scss │ │ └── user-info.ts ├── service-worker.js └── theme │ └── variables.scss ├── tsconfig.json └── tslint.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | 10 | # We recommend you to keep these unchanged 11 | end_of_line = lf 12 | charset = utf-8 13 | trim_trailing_whitespace = true 14 | insert_final_newline = true 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Specifies intentionally untracked files to ignore when using Git 2 | # http://git-scm.com/docs/gitignore 3 | 4 | *~ 5 | *.sw[mnpcod] 6 | *.log 7 | *.tmp 8 | *.tmp.* 9 | log.txt 10 | *.sublime-project 11 | *.sublime-workspace 12 | .vscode/ 13 | npm-debug.log* 14 | 15 | .idea/ 16 | .sourcemaps/ 17 | .sass-cache/ 18 | .tmp/ 19 | .versions/ 20 | coverage/ 21 | dist/ 22 | node_modules/ 23 | tmp/ 24 | temp/ 25 | hooks/ 26 | platforms/ 27 | plugins/ 28 | plugins/android.json 29 | plugins/ios.json 30 | www/ 31 | $RECYCLE.BIN/ 32 | 33 | .DS_Store 34 | Thumbs.db 35 | UserInterfaceState.xcuserstate 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 介绍 2 | 此项目是一个简单的ionic App,包含以下几点常用功能: 3 | 4 | 1. 屏幕适配 5 | 2. 常用工具封装 6 | 3. Tab图标替换 7 | 4. 字体库替换 8 | 5. Echarts使用 9 | 6. 自定义通讯录 10 | 7. 数据库 11 | 8. 版本信息 12 | 13 | 我会抽空将此APP完善,添加更多的功能,供大家参考,假如有任何的建议或者意见,请提issue,我会及时回复。 14 | 15 | 我的博客也放置在 `GitHub` 仓库 [Blog](https://github.com/JerryMissTom/Blog/issues) 上,里面有我在 `ionic` 实践过程中的踩坑心得,可以参考下。 16 | 17 | ## 开发环境 18 | 1. ionic V3.10.3 19 | 2. cordova V7.0.1 20 | 3. npm V5.4.1 21 | 4. node V8.1.4 22 | 23 | ## 用法 24 | 25 | #### 初始化项目 26 | 顺序执行以下操作: 27 | ``` 28 | //空白文件夹下 29 | git clone https://github.com/JerryMissTom/HW-basic.git 30 | 31 | // 项目根目录下: 32 | npm install 33 | 34 | //安装 App Version 插件 35 | ionic cordova plugin add cordova-plugin-app-version 36 | 37 | //安装 Keyboard 插件 38 | ionic cordova plugin add ionic-plugin-keyboard 39 | 40 | //安装 Sqlite 插件 41 | ionic cordova plugin add cordova-sqlite-storage 42 | ``` 43 | #### 打包 44 | Android环境 45 | 确保已经安装了相应Android SDK,建议通过Android Studio来安装,简单方便 46 | ``` 47 | // 添加android平台 48 | ionic cordova platform add android 49 | 50 | // 打包 51 | ionic cordova build android --prod 52 | ``` 53 | 然后使用 `Android Studio` 打开项目下 `platform/android` 文件夹进行签名打包 54 | 55 | 56 | iOS 环境 57 | 确保安装Xcode,并配置好相关SDK 58 | ``` 59 | // 添加iOS平台 60 | ionic cordova platform add ios 61 | 62 | // 打包 63 | ionic cordova build ios --prod 64 | ``` 65 | 然后使用 `Xcode` 打开项目下 `platform/ios` 文件夹进行签名打包 66 | 67 | #### 调试 68 | 浏览器调试,只适合调试界面和接口,无法调试原生功能,代码修改并保存后会自动构建,可以看到结果。 69 | ``` 70 | //根目录下执行 71 | ionic serve 72 | ``` 73 | 74 | 安卓调试,适合调试原生功能,如数据库,照相机等 75 | 76 | 打开手机的开发者选项和USB调试,手机通过USB与电脑连接,执行`adb devices`可以查看手机是否与电脑连接成功,然后项目根目录下执行 `ionic cordova run android` 将APP安装至手机并运行,打开Chrome浏览器,在地址栏输入 `chrome://inspect`(第一次打开需要翻墙),可以看到需要调试的APP,点击下方的`inspect`可以看到手机的界面,并且在`console`中查看日志。 77 | -------------------------------------------------------------------------------- /config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | HW-basic 4 | 简单基础的ionic App 5 | JerryMissTom 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "HW-basic", 3 | "app_id": "", 4 | "type": "ionic-angular", 5 | "integrations": { 6 | "cordova": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "HW-basic", 3 | "version": "0.0.1", 4 | "author": "JerryMissTom", 5 | "homepage": "https://github.com/JerryMissTom", 6 | "private": true, 7 | "scripts": { 8 | "clean": "ionic-app-scripts clean", 9 | "build": "ionic-app-scripts build", 10 | "lint": "ionic-app-scripts lint", 11 | "ionic:build": "ionic-app-scripts build", 12 | "ionic:serve": "ionic-app-scripts serve" 13 | }, 14 | "dependencies": { 15 | "@angular/common": "5.0.0", 16 | "@angular/compiler": "5.0.0", 17 | "@angular/compiler-cli": "5.0.0", 18 | "@angular/core": "5.0.0", 19 | "@angular/forms": "5.0.0", 20 | "@angular/http": "5.0.0", 21 | "@angular/platform-browser": "5.0.0", 22 | "@angular/platform-browser-dynamic": "5.0.0", 23 | "@ionic-native/app-version": "^4.5.2", 24 | "@ionic-native/core": "4.3.2", 25 | "@ionic-native/keyboard": "^4.5.2", 26 | "@ionic-native/splash-screen": "4.3.2", 27 | "@ionic-native/sqlite": "^4.5.2", 28 | "@ionic-native/status-bar": "4.3.2", 29 | "@ionic/storage": "2.1.3", 30 | "cordova-plugin-app-version": "^0.1.9", 31 | "cordova-sqlite-storage": "^2.2.0", 32 | "echarts": "^4.0.2", 33 | "ionic-angular": "3.9.2", 34 | "ionic-plugin-keyboard": "^2.2.1", 35 | "ionicons": "3.0.0", 36 | "rxjs": "5.5.2", 37 | "sw-toolbox": "3.6.0", 38 | "ws": "^3.3.2", 39 | "zone.js": "0.8.18" 40 | }, 41 | "devDependencies": { 42 | "@ionic/app-scripts": "3.1.0", 43 | "typescript": "2.4.2" 44 | }, 45 | "description": "简单基础的ionic App", 46 | "cordova": { 47 | "plugins": { 48 | "ionic-plugin-keyboard": {}, 49 | "cordova-sqlite-storage": {}, 50 | "cordova-plugin-app-version": {} 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /resources/README.md: -------------------------------------------------------------------------------- 1 | These are Cordova resources. You can replace icon.png and splash.png and run 2 | `ionic cordova resources` to generate custom icons and splash screens for your 3 | app. See `ionic cordova resources --help` for details. 4 | 5 | Cordova reference documentation: 6 | 7 | - Icons: https://cordova.apache.org/docs/en/latest/config_ref/images.html 8 | - Splash Screens: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-splashscreen/ 9 | -------------------------------------------------------------------------------- /resources/android/icon/drawable-hdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/icon/drawable-hdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-ldpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/icon/drawable-ldpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-mdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/icon/drawable-mdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-xhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/icon/drawable-xhdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-xxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/icon/drawable-xxhdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-xxxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/icon/drawable-xxxhdpi-icon.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-land-hdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-land-ldpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-land-mdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-land-xhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-land-xxhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-land-xxxhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-port-hdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-port-ldpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-port-mdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-port-xhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-port-xxhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/android/splash/drawable-port-xxxhdpi-screen.png -------------------------------------------------------------------------------- /resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/icon.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-1024.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-40.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-40@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-40@3x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-50.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-50@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-60.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-60@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-60@3x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-72.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-72@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-76.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-76@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-83.5@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-small.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-small@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon-small@3x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon.png -------------------------------------------------------------------------------- /resources/ios/icon/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/icon/icon@2x.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-568h@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-568h@2x~iphone.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-667h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-667h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-736h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-Landscape-736h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-Landscape@2x~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape@~ipadpro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-Landscape@~ipadpro.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-Landscape~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-Portrait@2x~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait@~ipadpro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-Portrait@~ipadpro.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default-Portrait~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default@2x~iphone.png -------------------------------------------------------------------------------- /resources/ios/splash/Default@2x~universal~anyany.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default@2x~universal~anyany.png -------------------------------------------------------------------------------- /resources/ios/splash/Default~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/ios/splash/Default~iphone.png -------------------------------------------------------------------------------- /resources/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/resources/splash.png -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Platform } from 'ionic-angular'; 3 | import { StatusBar } from '@ionic-native/status-bar'; 4 | import { SplashScreen } from '@ionic-native/splash-screen'; 5 | 6 | import { TabsPage } from '../pages/tabs/tabs'; 7 | import { DBService } from '../core/db'; 8 | import { LoginComponent } from '../pages/login/login'; 9 | 10 | @Component({ 11 | templateUrl: 'app.html' 12 | }) 13 | export class MyApp { 14 | rootPage: any = LoginComponent; 15 | 16 | constructor(platform: Platform, 17 | statusBar: StatusBar, 18 | splashScreen: SplashScreen, 19 | private db: DBService) { 20 | platform.ready().then(() => { 21 | // Okay, so the platform is ready and our plugins are available. 22 | // Here you can do any higher level native things you might need. 23 | statusBar.styleDefault(); 24 | splashScreen.hide(); 25 | 26 | // 初始化数据库 27 | this.db.initDB(); 28 | 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/app.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, ErrorHandler } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular'; 4 | 5 | import { StatusBar } from '@ionic-native/status-bar'; 6 | import { SplashScreen } from '@ionic-native/splash-screen'; 7 | import { AppVersion } from '@ionic-native/app-version'; 8 | import { SQLite } from "@ionic-native/sqlite"; 9 | import { Keyboard } from '@ionic-native/keyboard'; 10 | 11 | import { MyApp } from './app.component'; 12 | import { AboutPage } from '../pages/about/about'; 13 | import { ContactPage } from '../pages/contact/contact'; 14 | import { HomePage } from '../pages/home/home'; 15 | import { TabsPage } from '../pages/tabs/tabs'; 16 | import { CoreModule } from '../core/core.module'; 17 | import { LoginComponent } from '../pages/login/login'; 18 | 19 | @NgModule({ 20 | declarations: [ 21 | MyApp, 22 | LoginComponent, 23 | AboutPage, 24 | ContactPage, 25 | HomePage, 26 | TabsPage 27 | ], 28 | imports: [ 29 | CoreModule, 30 | BrowserModule, 31 | // 更多的配置参见:https://ionicframework.com/docs/api/config/Config/ 32 | IonicModule.forRoot(MyApp, { 33 | backButtonText: "", 34 | tabsHideOnSubPages: true, 35 | mode: 'ios' 36 | }) 37 | ], 38 | bootstrap: [IonicApp], 39 | entryComponents: [ 40 | MyApp, 41 | LoginComponent, 42 | AboutPage, 43 | ContactPage, 44 | HomePage, 45 | TabsPage 46 | ], 47 | providers: [ 48 | StatusBar, 49 | SplashScreen, 50 | AppVersion, 51 | Keyboard, 52 | SQLite, 53 | { provide: ErrorHandler, useClass: IonicErrorHandler } 54 | ] 55 | }) 56 | export class AppModule { } 57 | -------------------------------------------------------------------------------- /src/app/app.scss: -------------------------------------------------------------------------------- 1 | // http://ionicframework.com/docs/theming/ 2 | // App Global Sass 3 | // -------------------------------------------------- 4 | // Put style rules here that you want to apply globally. These 5 | // styles are for the entire app and not just one component. 6 | // Additionally, this file can be also used as an entry point 7 | // to import other Sass files to be included in the output CSS. 8 | // 9 | // Shared Sass variables, which can be used to adjust Ionic's 10 | // default Sass variables, belong in "theme/variables.scss". 11 | // 12 | // To declare rules for a specific mode, create a child rule 13 | // for the .md, .ios, or .wp mode classes. The mode class is 14 | // automatically applied to the element in the app. 15 | // 页面适配 16 | // 根元素大小使用 vw 单位 17 | $vm_fontsize: 36; // 是$vm_design 值得十分之一 18 | $vm_design: 360; // 根据需要替换成设计稿的值,比如设计稿给你的宽度是360px, 19 | html { 20 | font-size: ($vm_fontsize / $vm_design) * 100vw; // 同时,通过Media Queries 限制根元素最大最小值 21 | @media screen and (max-width: 320px) { 22 | font-size: 32px; 23 | } 24 | @media screen and (min-width: 540px) { 25 | font-size: 54px; 26 | } 27 | } 28 | 29 | // body 也增加最大最小宽度限制,避免默认100%宽度的 block 元素跟随 body 而过大过小 30 | body { 31 | max-width: 540px; 32 | min-width: 320px; 33 | } 34 | 35 | html { 36 | width: 100%; 37 | height: 100%; 38 | margin: 0; 39 | padding: 0; 40 | -webkit-text-size-adjust: 100%; 41 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 42 | background: transparent; 43 | box-sizing: border-box; 44 | } 45 | 46 | body { 47 | width: 100%; 48 | height: 100%; 49 | -webkit-overflow-scrolling: touch; 50 | } 51 | 52 | body, 53 | div, 54 | dl, 55 | dt, 56 | dd, 57 | ul, 58 | ol, 59 | li, 60 | h1, 61 | h2, 62 | h3, 63 | h4, 64 | h5, 65 | h6, 66 | pre, 67 | code, 68 | form, 69 | fieldset, 70 | legend, 71 | input, 72 | textarea, 73 | p, 74 | blockquote, 75 | th, 76 | td, 77 | hr, 78 | button, 79 | article, 80 | aside, 81 | details, 82 | figcaption, 83 | figure, 84 | footer, 85 | header, 86 | hgroup, 87 | menu, 88 | nav, 89 | section, 90 | sumary { 91 | margin: 0; 92 | padding: 0; 93 | } 94 | 95 | //清除输入框内阴影 96 | input, 97 | select, 98 | textarea { 99 | border: 0; 100 | -webkit-appearance: none; 101 | appearance: none; 102 | } 103 | 104 | ol, 105 | ul { 106 | list-style: none; 107 | } 108 | 109 | //禁止选中文本内容 110 | *:not(input, select, textArea) { 111 | -webkit-user-select: none; 112 | } 113 | 114 | //禁用长按页面时的弹出菜单(iOS下有效) ,img和a标签都要加 115 | img, 116 | a { 117 | -webkit-touch-callout: none; 118 | } 119 | 120 | a, 121 | a:active, 122 | a:hover { 123 | text-decoration: none; 124 | } 125 | 126 | //去掉点击链接和文本框对象时默认的灰色半透明覆盖层(iOS)或者虚框(Android) 127 | a, 128 | button, 129 | input, 130 | textarea { 131 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 132 | } 133 | 134 | .back-button-icon-md, 135 | .back-button-icon-ios { 136 | font-size: rem(28); 137 | } 138 | 139 | .back-button-ios { 140 | min-height: rem(32); 141 | } 142 | 143 | //icon 定位在页面的右侧,添加在ion-icon 标签上 144 | .icon-right { 145 | position: absolute; 146 | right: 10%; 147 | top: 50%; 148 | transform: translateY(-50%); 149 | } 150 | 151 | //item固有高度 152 | .item-block { 153 | min-height: rem(44); 154 | } 155 | 156 | //checkbox框样式 157 | .checkbox-ios .checkbox-icon { 158 | border-radius: 4px; 159 | } 160 | 161 | .item.item-ios .checkbox-ios { 162 | margin: rem(15) 0; 163 | margin-right: rem(9); 164 | } 165 | 166 | //菜单图标 167 | .bar-button-menutoggle-ios ion-icon { 168 | font-size: rem(24); 169 | } 170 | 171 | //icon 172 | .item>ion-icon, 173 | .item-inner>ion-icon { 174 | font-size: rem(28); 175 | min-height: rem(28); 176 | } 177 | 178 | // 时间选择器配置 179 | .picker-ios .picker-opt { 180 | height: rem(45); 181 | } 182 | 183 | .center { 184 | display: -webkit-box; 185 | display: -moz-box; 186 | display: -ms-flexbox; 187 | display: -webkit-flex; 188 | display: flex; 189 | align-items: center; 190 | justify-content: center; 191 | -webkit-box-pack: center; 192 | -webkit-justify-content: center; 193 | } 194 | 195 | .space-between { 196 | display: -webkit-box; 197 | display: -moz-box; 198 | display: -ms-flexbox; 199 | display: -webkit-flex; 200 | display: flex; 201 | align-items: center; 202 | justify-content: space-between; 203 | } 204 | 205 | .space-around { 206 | display: -webkit-box; 207 | display: -moz-box; 208 | display: -ms-flexbox; 209 | display: -webkit-flex; 210 | display: flex; 211 | align-items: center; 212 | justify-content: space-around; 213 | } 214 | 215 | .toast-middle{ 216 | width: 50px; 217 | } 218 | .toast-ios .toast-message{ 219 | text-align: center; 220 | } -------------------------------------------------------------------------------- /src/app/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /src/assets/icon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/src/assets/icon/favicon.ico -------------------------------------------------------------------------------- /src/assets/imgs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JerryMissTom/HW-basic/d81dd8db499fad762005f88543cb828d5655108c/src/assets/imgs/logo.png -------------------------------------------------------------------------------- /src/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { HttpModule } from '@angular/http'; 3 | import { DBService } from './db'; 4 | import { Util } from './utils'; 5 | import { ErrorService } from './error'; 6 | import { HttpService } from './http'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | HttpModule 11 | ], 12 | providers: [ 13 | DBService, 14 | Util, 15 | ErrorService, 16 | HttpService 17 | ] 18 | }) 19 | 20 | export class CoreModule { } -------------------------------------------------------------------------------- /src/core/db.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Injectable } from '@angular/core'; 3 | import { SQLite, SQLiteObject } from '@ionic-native/sqlite' 4 | 5 | @Injectable() 6 | export class DBService { 7 | 8 | myDataBase: SQLiteObject; 9 | 10 | constructor( 11 | private sqlite: SQLite 12 | ) { } 13 | 14 | 15 | //初始化或打开数据库,建立表 16 | initDB() { 17 | this.sqlite.create({ 18 | name: 'basic.db', 19 | location: 'default' 20 | }).then((database: SQLiteObject) => { 21 | // 创建客户信息表 22 | let sqlStr = ' create table if not exists contact ' + 23 | '(' + 24 | 'id INTEGER PRIMARY KEY autoincrement, ' + 25 | 'name text, ' + // 姓名 26 | 'phone text, ' + //号码 27 | 'index text, ' + // 检索字母,即 a-z,# 28 | ')'; 29 | 30 | database.executeSql(sqlStr, {}).then(() => { 31 | console.log('创建表成功'); 32 | 33 | }).catch(() => { 34 | console.log('创建表失败'); 35 | }); 36 | 37 | this.myDataBase = database; 38 | }).catch(() => { 39 | console.log('打开数据库失败'); 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/core/error.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { ToastController, NavController } from 'ionic-angular'; 3 | 4 | @Injectable() 5 | export class ErrorService { 6 | 7 | constructor( 8 | private toastCtrl: ToastController 9 | ) { 10 | } 11 | 12 | public handleError(errorCode) { 13 | let errorMessage = this.getErrorMessage(errorCode); 14 | this.toastCtrl.create({ 15 | message: errorMessage, 16 | duration: 1300, 17 | position: 'bottom' 18 | }).present(); 19 | } 20 | 21 | private getErrorMessage(errorCode: number): string { 22 | 23 | let errorMessage: string; 24 | switch (errorCode) { 25 | case 500: 26 | errorMessage = '服务器开小差了'; 27 | break; 28 | case 404: 29 | errorMessage = '未找到该资源'; 30 | break; 31 | default: 32 | errorMessage = '服务器错误'; 33 | 34 | } 35 | return errorMessage; 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/core/http.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Headers, Http, RequestOptions, Response } from '@angular/http'; 3 | 4 | import { Observable } from 'rxjs/Observable'; 5 | import 'rxjs/add/operator/map'; 6 | import 'rxjs/add/operator/catch'; 7 | import 'rxjs/add/observable/throw'; 8 | import 'rxjs/add/operator/timeout'; 9 | 10 | @Injectable() 11 | export class HttpService { 12 | 13 | private environmentUrl = ''; 14 | 15 | constructor( 16 | private http: Http 17 | ) { } 18 | 19 | // post 方法 20 | public post(requestUrl, requestJson) { 21 | return this.httpRequestPost(requestUrl, requestJson) 22 | .map(response => response.json()) 23 | .catch(this.handlerError) 24 | } 25 | 26 | // get 方法 27 | public get(param: string) { 28 | const header: any = new Headers({ 'Content-type': 'application/json' }); 29 | const options: any = new RequestOptions({ headers: header }); 30 | return this.http.get(this.environmentUrl + param, options) 31 | .timeout(10000).map(response => response.json()).catch(this.handlerError); 32 | } 33 | 34 | private httpRequestPost(requestUrl, requestJson) { 35 | const body: string = JSON.stringify(requestJson); 36 | const header: any = new Headers({ 'Content-type': 'application/json' }); 37 | const options: any = new RequestOptions({ headers: header }); 38 | return this.http.post(this.environmentUrl + requestUrl, body, options) 39 | .timeout(10000) 40 | } 41 | 42 | private handlerError(error: Response | any) { 43 | const body = error.json() || {}; 44 | return Observable.throw(body); 45 | } 46 | } -------------------------------------------------------------------------------- /src/core/utils.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { Platform } from 'ionic-angular'; 3 | 4 | @Injectable() 5 | export class Util { 6 | 7 | constructor(private platform: Platform) { 8 | } 9 | 10 | // 获取平台类型 11 | getNavigator(): string { 12 | 13 | if (this.platform.is('android')) { 14 | return 'android'; 15 | } 16 | 17 | if (this.platform.is('ios')) { 18 | return 'ios'; 19 | } 20 | 21 | return 'android'; 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HW-basic 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "HW-basic", 3 | "short_name": "HW-basic", 4 | "start_url": "index.html", 5 | "display": "standalone", 6 | "icons": [{ 7 | "src": "assets/imgs/logo.png", 8 | "sizes": "512x512", 9 | "type": "image/png" 10 | }], 11 | "background_color": "#4e8ef7", 12 | "theme_color": "#4e8ef7" 13 | } -------------------------------------------------------------------------------- /src/pages/about/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | About 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | JerryMissTom 13 |
14 |
15 | 版本号 16 | {{version}} 17 |
18 |
19 | 用户信息 20 | 21 |
22 |
23 | -------------------------------------------------------------------------------- /src/pages/about/about.scss: -------------------------------------------------------------------------------- 1 | page-about { 2 | .user-header { 3 | width: 100%; 4 | height: rem(100); 5 | flex-direction: column; 6 | margin: rem(20) 0; 7 | .avatar { 8 | width: rem(80); 9 | height: rem(80); 10 | background: #488aff; 11 | border-radius: 100%; 12 | } 13 | } 14 | .first-item { 15 | border-top: #ececec solid rem(1); 16 | } 17 | .item { 18 | width: 100%; 19 | height: rem(50); 20 | padding: 0 rem(10); 21 | border-bottom: #ececec solid rem(1); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/pages/about/about.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NavController } from 'ionic-angular'; 3 | import { AppVersion } from '@ionic-native/app-version'; 4 | 5 | @Component({ 6 | selector: 'page-about', 7 | templateUrl: 'about.html' 8 | }) 9 | export class AboutPage { 10 | 11 | private version; 12 | constructor( 13 | public navCtrl: NavController, 14 | private appVersion: AppVersion 15 | ) { 16 | this.version = ''; 17 | } 18 | 19 | ionViewDidLoad() { 20 | this.appVersion.getVersionNumber().then(num => { 21 | this.version = this.version + num; 22 | }); 23 | } 24 | 25 | private toUserPage() { 26 | this.navCtrl.push('UserInfoPage'); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/pages/contact/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Contact 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 | 18 |
19 |
20 |
21 | 22 |
23 | {{item.index}} 24 |
25 |
26 | {{item.firstLetter}} 27 | {{item.name}} 28 | {{item.phone}} 29 |
30 |
31 |
32 |
33 |
34 | 39 |
40 |
41 | -------------------------------------------------------------------------------- /src/pages/contact/contact.scss: -------------------------------------------------------------------------------- 1 | page-contact { 2 | .search-field { 3 | width: 100%; 4 | height: rem(52); 5 | align-items: center; 6 | flex-direction: column; 7 | padding: rem(6) rem(0); 8 | background: #FFFFFF; 9 | .search { 10 | width: 90%; 11 | height: rem(40); 12 | padding: rem(5) rem(10); 13 | border: rgb(216, 213, 213) solid rem(1); 14 | border-radius: rem(40); 15 | .keyword { 16 | width: 100%; 17 | height: rem(39); 18 | padding: rem(0) rem(6); 19 | background: none; 20 | font-size: rem(15); 21 | } 22 | } 23 | } 24 | .content { 25 | width: 100%; 26 | display: flex; 27 | flex-direction: row; 28 | } 29 | .left { 30 | width: 95%; 31 | .contact-list { 32 | width: 100%; 33 | .index-item { 34 | width: 100%; 35 | height: rem(20); 36 | background: #ececec; 37 | color: black; 38 | font-size: rem(12); 39 | line-height: rem(20); 40 | padding: rem(0) rem(10); 41 | } 42 | .contact-item { 43 | height: rem(60); 44 | width: 100%; 45 | border-bottom: #ececec solid rem(1); 46 | padding: rem(0) rem(10); 47 | align-items: center; 48 | .first-letter { 49 | width: rem(45); 50 | height: rem(45); 51 | border-radius: 100%; 52 | background: #D8D8D8; 53 | text-align: center; 54 | line-height: rem(45); 55 | color: black; 56 | font-family: HoneywellSans-Medium; 57 | font-size: rem(18); 58 | } 59 | .contact-name { 60 | height: rem(45); 61 | line-height: rem(45); 62 | font-size: rem(16); 63 | text-align: left; 64 | width: 40%; 65 | display: -webkit-box; 66 | -webkit-box-orient: vertical; 67 | -webkit-line-clamp: 1; 68 | overflow: hidden; 69 | color: #303030; 70 | letter-spacing: -0.39px; 71 | font-family: HoneywellSans-Medium; 72 | } 73 | .contact-phone { 74 | height: rem(45); 75 | line-height: rem(45); 76 | font-family: HoneywellSans-Medium; 77 | font-size: rem(16); 78 | text-align: right; 79 | width: 40%; 80 | display: -webkit-box; 81 | -webkit-box-orient: vertical; 82 | -webkit-line-clamp: 2; 83 | overflow: hidden; 84 | letter-spacing: -0.39px; 85 | } 86 | } 87 | } 88 | .ios-list-header { 89 | position: sticky; 90 | z-index: 1; 91 | top: 0; 92 | } 93 | .android-list-header { 94 | position: fixed; 95 | z-index: 1; 96 | top: rem(38); 97 | } 98 | .android-list-top { 99 | margin-top: rem(52) !important; 100 | } 101 | .ios-list-bottom { 102 | padding-bottom: rem(34); 103 | } 104 | } 105 | .nav { 106 | width: 5%; 107 | font-size: rem(14); 108 | ul { 109 | width: 100%; 110 | height: 100%; 111 | appearance: none; 112 | padding: 0; 113 | } 114 | li { 115 | width: 100%; 116 | appearance: none; 117 | list-style-type: none; 118 | color: #488aff; 119 | text-align: center; 120 | } 121 | } 122 | .android-nav { 123 | position: fixed; 124 | z-index: 1; 125 | right: 0; 126 | top: rem(70); 127 | height: 85%; 128 | } 129 | .ios-nav { 130 | position: sticky; 131 | z-index: 1; 132 | top: rem(30); 133 | right: 0; 134 | height: 85%; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/pages/contact/contact.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, ViewChild } from '@angular/core'; 2 | import { NavController, LoadingController, Events, Content, ToastController } from 'ionic-angular'; 3 | import { Subject } from 'rxjs/Subject'; 4 | import 'rxjs/add/operator/debounceTime'; 5 | import { Observable } from 'rxjs/Observable'; 6 | import { Observer } from 'rxjs/Observer'; 7 | import { Subscription } from 'rxjs/Subscription'; 8 | import { Keyboard } from '@ionic-native/keyboard'; 9 | import { Util } from '../../core/utils'; 10 | import { DBService } from '../../core/db'; 11 | import { contacts, mockContacts } from './mock-data'; 12 | 13 | @Component({ 14 | selector: 'page-contact', 15 | templateUrl: 'contact.html' 16 | }) 17 | export class ContactPage { 18 | 19 | @ViewChild(Content) content: Content; 20 | private version: string; 21 | private searchWord: string; 22 | private textEmitter: Subject = new Subject(); 23 | private eventBus: Observable; 24 | private observer: Observer; 25 | private hideSubscription: Subscription; 26 | private showSubscription: Subscription; 27 | private loading: any; 28 | private contacts; 29 | private letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '#']; 30 | 31 | 32 | constructor( 33 | private keyboard: Keyboard, 34 | private event: Events, 35 | private navCtrl: NavController, 36 | private loadingCtrl: LoadingController, 37 | private elementRef: ElementRef, 38 | private util: Util, 39 | private db: DBService, 40 | private toastCtrl: ToastController 41 | ) { 42 | this.version = this.util.getNavigator(); 43 | this.searchWord = ''; 44 | this.loading = null; 45 | // 真机上调试时将其注释掉 46 | this.contacts = contacts; 47 | // 真机上调试,把下面的注释去掉 48 | // this.initData(); 49 | // this.getDataFromDB(); 50 | this.eventBus = new Observable(observer => 51 | this.observer = observer).debounceTime(500); 52 | this.eventBus.subscribe(text => { 53 | if (text) { 54 | this.getDataFromDB(text); 55 | } 56 | }); 57 | } 58 | 59 | private initData() { 60 | let sqls = []; 61 | for (let item of mockContacts) { 62 | let childItem = []; 63 | let firstStr = 'replace into contact' + 64 | '(name,' + 65 | 'phone,' + 66 | 'index) ' + 67 | 'values (?,?,?)'; 68 | childItem.push(firstStr); 69 | let second = [ 70 | item.name, item.phone, item.index, 71 | ]; 72 | childItem.push(second); 73 | sqls.push(childItem); 74 | } 75 | 76 | return this.db.myDataBase.sqlBatch(sqls).then(() => { 77 | console.log('批量插入成功'); 78 | }).catch(() => { 79 | console.log('批量插入失败'); 80 | }); 81 | } 82 | 83 | ionViewDidEnter() { 84 | // 注册监听输入法的打开和关闭,然后发射此事件,在Tab.st中执行Tab的打开和关闭 85 | this.hideSubscription = this.keyboard.onKeyboardShow().subscribe(() => this.event.publish('hideTabs')); 86 | this.showSubscription = this.keyboard.onKeyboardHide().subscribe(() => this.event.publish('showTabs')); 87 | } 88 | 89 | private scrollTo(letter) { 90 | 91 | this.toastCtrl.create({ 92 | message: letter, 93 | duration: 1000, 94 | position: 'middle' 95 | }).present(); 96 | 97 | if (letter === '#') { 98 | letter = '\\#'; 99 | } 100 | //获取第一个标签的位置 101 | let topLocation = 0; 102 | for (let item in this.letters) { 103 | let itemDom = this.elementRef.nativeElement.querySelector('div#' + this.letters[item]); 104 | if (itemDom) { 105 | topLocation = itemDom.getBoundingClientRect().top; 106 | break; 107 | } 108 | } 109 | 110 | let ele = this.elementRef.nativeElement.querySelector('div#' + letter); 111 | if (ele) { 112 | let s = ele.getBoundingClientRect(); 113 | this.content.scrollTo(0, s.top - topLocation, 300); // 这个是重点,Y轴移动相对第一个标签的位置 114 | } 115 | } 116 | 117 | private getDataFromDB(text?: string) { 118 | 119 | if (text) { 120 | let sql = "select * from contact where name like '%" + text + "%'" + " or phone like '%" + text + "%'" + " order by index"; 121 | console.log(sql); 122 | this.db.myDataBase.executeSql(sql, {}).then(data => { 123 | console.log('查询' + text + '数据成功'); 124 | this.contacts = this.setContracts(data); 125 | }).catch(erroe => { 126 | console.log('查询' + text + '数据失败'); 127 | }); 128 | } else { 129 | let sql = "select * from contact order by index"; 130 | console.log(sql); 131 | this.db.myDataBase.executeSql(sql, {}).then(data => { 132 | console.log('获取所有数据成功'); 133 | this.contacts = this.setContracts(data); 134 | }).catch(erroe => { 135 | console.log('获取所有数据失败'); 136 | }); 137 | } 138 | } 139 | 140 | private onInput(event) { 141 | this.observer.next(event.target.value.trim()); 142 | } 143 | 144 | private onClear(event) { 145 | this.keyboard.close(); 146 | this.searchWord = ''; 147 | this.presentLoading(); 148 | this.getDataFromDB(); 149 | this.dismissLoading(); 150 | } 151 | 152 | private setContracts(data) { 153 | 154 | const length = data.rows.length; 155 | let showList = []; // 最后的数组 156 | let specialList = []; // 属于#的客户 157 | let rows = data.rows; 158 | 159 | for (let i = 0; i < length; i++) { 160 | 161 | //把属于特殊字符的先提取出来 162 | if (rows.item(i).index.trim() === '#') { 163 | let specialItem = { 164 | name: rows.item(i).name, 165 | phone: rows.item(i).phone, 166 | type: 1, //1 表示是数据 167 | firstLetter: rows.item(i).name.charAt(0), 168 | index: rows.item(i).index 169 | } 170 | specialList.push(specialItem); 171 | continue; 172 | } 173 | 174 | // 前后两个数据的Index不同时,在中间插上索引 175 | if (i === 0 || rows.item(i).index.trim() !== rows.item(i - 1).index.trim()) { 176 | let item = { 177 | type: 0, //0 表示是索引 178 | index: rows.item(i).index.toUpperCase() 179 | } 180 | showList.push(item); 181 | } 182 | 183 | let dataItem = { 184 | name: rows.item(i).name, 185 | phone: rows.item(i).phone, 186 | type: 1, //1 表示是数据 187 | firstLetter: rows.item(i).name.charAt(0), 188 | index: rows.item(i).index 189 | } 190 | showList.push(dataItem); 191 | } 192 | 193 | //把属于#的加上索引,并放置在数组最后 194 | if (specialList.length > 0) { 195 | let item = { 196 | type: 0, //0 表示是索引 197 | index: '#' 198 | } 199 | showList.push(item); 200 | return showList.concat(specialList); 201 | } else { 202 | return showList; 203 | } 204 | } 205 | 206 | private presentLoading() { 207 | if (!this.loading) { 208 | this.loading = this.loadingCtrl.create({ 209 | content: '请稍候' 210 | }); 211 | this.loading.present(); 212 | } 213 | } 214 | 215 | private dismissLoading() { 216 | if (this.loading) { 217 | this.loading.dismiss(); 218 | this.loading = null; 219 | } 220 | } 221 | 222 | ionViewWillLeave() { 223 | // 解除监听事件 224 | this.keyboard.close(); 225 | if (this.hideSubscription) { 226 | this.hideSubscription.unsubscribe(); 227 | this.hideSubscription = null; 228 | } 229 | if (this.showSubscription) { 230 | this.showSubscription.unsubscribe(); 231 | this.showSubscription = null; 232 | } 233 | this.dismissLoading(); 234 | } 235 | 236 | } 237 | -------------------------------------------------------------------------------- /src/pages/contact/mock-data.ts: -------------------------------------------------------------------------------- 1 | export const contacts = [ 2 | { 3 | type: 0, 4 | index: 'B' 5 | }, 6 | { 7 | type: 1, 8 | index: 'A', 9 | firstLetter: '好', 10 | name: '公司', 11 | phone: '1236777' 12 | }, 13 | { 14 | type: 1, 15 | index: 'A', 16 | firstLetter: '好', 17 | name: '公司', 18 | phone: '1236777' 19 | }, 20 | { 21 | type: 1, 22 | index: 'A', 23 | firstLetter: '好', 24 | name: '公司', 25 | phone: '1236777' 26 | }, 27 | { 28 | type: 1, 29 | index: 'A', 30 | firstLetter: '好', 31 | name: '公司', 32 | phone: '1236777' 33 | }, 34 | { 35 | type: 0, 36 | index: 'C' 37 | }, 38 | { 39 | type: 1, 40 | index: 'A', 41 | firstLetter: '好', 42 | name: '公司', 43 | phone: '1236777' 44 | }, 45 | { 46 | type: 1, 47 | index: 'A', 48 | firstLetter: '好', 49 | name: '公司', 50 | phone: '1236777' 51 | }, 52 | { 53 | type: 1, 54 | index: 'A', 55 | firstLetter: '好', 56 | name: '公司', 57 | phone: '1236777' 58 | }, 59 | { 60 | type: 1, 61 | index: 'A', 62 | firstLetter: '好', 63 | name: '公司', 64 | phone: '1236777' 65 | }, 66 | { 67 | type: 0, 68 | index: 'D' 69 | }, 70 | { 71 | type: 1, 72 | index: 'A', 73 | firstLetter: '好', 74 | name: '公司', 75 | phone: '1236777' 76 | }, 77 | { 78 | type: 1, 79 | index: 'A', 80 | firstLetter: '好', 81 | name: '公司', 82 | phone: '1236777' 83 | }, 84 | { 85 | type: 1, 86 | index: 'A', 87 | firstLetter: '好', 88 | name: '公司', 89 | phone: '1236777' 90 | }, 91 | { 92 | type: 1, 93 | index: 'A', 94 | firstLetter: '好', 95 | name: '公司', 96 | phone: '1236777' 97 | }, 98 | { 99 | type: 0, 100 | index: 'E' 101 | }, 102 | { 103 | type: 1, 104 | index: 'A', 105 | firstLetter: '好', 106 | name: '公司', 107 | phone: '1236777' 108 | }, 109 | { 110 | type: 1, 111 | index: 'A', 112 | firstLetter: '好', 113 | name: '公司', 114 | phone: '1236777' 115 | }, 116 | { 117 | type: 1, 118 | index: 'A', 119 | firstLetter: '好', 120 | name: '公司', 121 | phone: '1236777' 122 | }, 123 | { 124 | type: 1, 125 | index: 'A', 126 | firstLetter: '好', 127 | name: '公司', 128 | phone: '1236777' 129 | }, 130 | { 131 | type: 0, 132 | index: '#' 133 | }, 134 | { 135 | type: 1, 136 | index: 'A', 137 | firstLetter: '好', 138 | name: '公司', 139 | phone: '1236777' 140 | }, 141 | { 142 | type: 1, 143 | index: 'A', 144 | firstLetter: '好', 145 | name: '公司', 146 | phone: '1236777' 147 | }, 148 | { 149 | type: 1, 150 | index: 'A', 151 | firstLetter: '好', 152 | name: '公司', 153 | phone: '1236777' 154 | }, 155 | { 156 | type: 1, 157 | index: 'A', 158 | firstLetter: '好', 159 | name: '公司', 160 | phone: '1236777' 161 | } 162 | ]; 163 | 164 | export const mockContacts = [ 165 | { 166 | index: 'A', 167 | name: '公司', 168 | phone: '1236777' 169 | }, 170 | { 171 | index: 'A', 172 | name: '公司', 173 | phone: '1236777' 174 | }, 175 | { 176 | index: 'A', 177 | name: '公司', 178 | phone: '1236777' 179 | }, 180 | { 181 | index: 'A', 182 | name: '公司', 183 | phone: '1236777' 184 | }, 185 | { 186 | index: 'A', 187 | name: '公司', 188 | phone: '1236777' 189 | }, 190 | { 191 | index: 'A', 192 | name: '公司', 193 | phone: '1236777' 194 | }, 195 | { 196 | index: 'A', 197 | name: '公司', 198 | phone: '1236777' 199 | }, 200 | { 201 | index: 'A', 202 | name: '公司', 203 | phone: '1236777' 204 | }, 205 | { 206 | index: 'A', 207 | name: '公司', 208 | phone: '1236777' 209 | }, 210 | { 211 | index: 'A', 212 | name: '公司', 213 | phone: '1236777' 214 | }, 215 | { 216 | index: 'A', 217 | name: '公司', 218 | phone: '1236777' 219 | }, 220 | { 221 | index: 'A', 222 | name: '公司', 223 | phone: '1236777' 224 | }, 225 | { 226 | index: 'A', 227 | name: '公司', 228 | phone: '1236777' 229 | }, 230 | { 231 | index: 'A', 232 | name: '公司', 233 | phone: '1236777' 234 | }, 235 | { 236 | index: 'A', 237 | name: '公司', 238 | phone: '1236777' 239 | }, 240 | { 241 | index: 'A', 242 | name: '公司', 243 | phone: '1236777' 244 | }, 245 | { 246 | index: 'A', 247 | name: '公司', 248 | phone: '1236777' 249 | }, 250 | { 251 | index: 'A', 252 | name: '公司', 253 | phone: '1236777' 254 | }, 255 | { 256 | index: 'A', 257 | name: '公司', 258 | phone: '1236777' 259 | }, 260 | { 261 | index: 'A', 262 | name: '公司', 263 | phone: '1236777' 264 | }, 265 | { 266 | index: 'A', 267 | name: '公司', 268 | phone: '1236777' 269 | }, 270 | { 271 | index: 'A', 272 | name: '公司', 273 | phone: '1236777' 274 | }, 275 | { 276 | index: 'A', 277 | name: '公司', 278 | phone: '1236777' 279 | } 280 | ]; 281 | -------------------------------------------------------------------------------- /src/pages/echarts/echarts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Echarts 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | -------------------------------------------------------------------------------- /src/pages/echarts/echarts.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { IonicPageModule } from 'ionic-angular'; 3 | import { EchartsPage } from './echarts'; 4 | 5 | @NgModule({ 6 | declarations: [ 7 | EchartsPage, 8 | ], 9 | imports: [ 10 | IonicPageModule.forChild(EchartsPage), 11 | ], 12 | }) 13 | export class EchartsPageModule {} 14 | -------------------------------------------------------------------------------- /src/pages/echarts/echarts.scss: -------------------------------------------------------------------------------- 1 | page-echarts { 2 | #main{ 3 | width: 100%; 4 | height: 300px; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/pages/echarts/echarts.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { IonicPage, NavController, NavParams } from 'ionic-angular'; 3 | import echarts from 'echarts'; 4 | @IonicPage() 5 | @Component({ 6 | selector: 'page-echarts', 7 | templateUrl: 'echarts.html', 8 | }) 9 | export class EchartsPage { 10 | 11 | constructor(public navCtrl: NavController, public navParams: NavParams) { 12 | } 13 | 14 | ionViewDidLoad() { 15 | let myChart = echarts.init(document.getElementById('main')); 16 | let option = { 17 | title: { 18 | text: 'ECharts示例' 19 | }, 20 | tooltip: {}, 21 | legend: { 22 | data: ['销量'] 23 | }, 24 | xAxis: { 25 | data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"] 26 | }, 27 | yAxis: {}, 28 | series: [{ 29 | name: '销量', 30 | type: 'bar', 31 | data: [5, 20, 36, 10, 10, 20] 32 | }] 33 | }; 34 | 35 | myChart.setOption(option); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/pages/home/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Home 4 | 5 | 6 | 7 | 8 |

Hi,HW-basic是一个简单基础的ionic App,里面都是我在真实项目中踩过得坑,实现了以下几个功能:

9 | 10 |
    11 |
  • 1.自定义字体
  • 12 |
  • 2.自定义Tab图标
  • 13 |
  • 3.自定义通讯录
  • 14 |
  • 4.屏幕适配
  • 15 |
  • 5.数据库
  • 16 |
  • 6.常用工具封装
  • 17 |
  • 7.版本信息
  • 18 |
  • 8.Echarts使用
  • 19 |
20 | 21 |

欢迎star、fork和issue

22 | 23 | 24 |
25 | -------------------------------------------------------------------------------- /src/pages/home/home.scss: -------------------------------------------------------------------------------- 1 | page-home { 2 | ul{ 3 | margin: rem(10) 0; 4 | } 5 | 6 | button{ 7 | width: auto; 8 | height: rem(20); 9 | font-size: 16px; 10 | line-height: rem(20); 11 | background: #488aff; 12 | } 13 | .devide{ 14 | margin-top: rem(20); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/pages/home/home.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { NavController } from 'ionic-angular'; 3 | 4 | @Component({ 5 | selector: 'page-home', 6 | templateUrl: 'home.html' 7 | }) 8 | export class HomePage { 9 | 10 | constructor(public navCtrl: NavController) { 11 | 12 | } 13 | 14 | toEchartsPage() { 15 | this.navCtrl.push('EchartsPage'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/pages/login/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 登录 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /src/pages/login/login.scss: -------------------------------------------------------------------------------- 1 | login { 2 | .login { 3 | width: 50%; 4 | height: rem(30); 5 | margin-top: rem(100); 6 | color: #488aff; 7 | font-size: 20px; 8 | border-radius: 5%; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/pages/login/login.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { TabsPage } from '../tabs/tabs'; 3 | import { NavController } from 'ionic-angular'; 4 | 5 | 6 | @Component({ 7 | selector: 'login', 8 | templateUrl: 'login.html' 9 | }) 10 | export class LoginComponent { 11 | 12 | 13 | constructor(private navCtrl: NavController) { 14 | 15 | } 16 | 17 | toHome() { 18 | this.navCtrl.setRoot(TabsPage); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/pages/tabs/tabs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/pages/tabs/tabs.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, Renderer, ViewChild } from '@angular/core'; 2 | import { Keyboard } from '@ionic-native/keyboard'; 3 | import { Events, Tabs } from 'ionic-angular'; 4 | 5 | import { AboutPage } from '../about/about'; 6 | import { ContactPage } from '../contact/contact'; 7 | import { HomePage } from '../home/home'; 8 | 9 | @Component({ 10 | templateUrl: 'tabs.html' 11 | }) 12 | export class TabsPage { 13 | 14 | @ViewChild('myTabs') tabRef: Tabs; 15 | mb: any; 16 | 17 | tab1Root = HomePage; 18 | tab2Root = ContactPage; 19 | tab3Root = AboutPage; 20 | 21 | constructor(private elementRef: ElementRef, 22 | private renderer: Renderer, 23 | private keyboard: Keyboard, 24 | private event: Events) { 25 | } 26 | 27 | ionViewDidLoad() { 28 | let tabs = this.queryElement(this.elementRef.nativeElement, '.tabbar'); 29 | this.event.subscribe('hideTabs', () => { 30 | console.log('hideTabs'); 31 | this.renderer.setElementStyle(tabs, 'display', 'none'); 32 | let SelectTab = this.tabRef.getSelected()._elementRef.nativeElement; 33 | let content = this.queryElement(SelectTab, '.scroll-content'); 34 | this.mb = content.style['margin-bottom']; 35 | this.renderer.setElementStyle(content, 'margin-bottom', '0') 36 | }); 37 | 38 | this.event.subscribe('showTabs', () => { 39 | console.log('showTabs'); 40 | this.renderer.setElementStyle(tabs, 'display', ''); 41 | let SelectTab = this.tabRef.getSelected()._elementRef.nativeElement; 42 | let content = this.queryElement(SelectTab, '.scroll-content'); 43 | this.renderer.setElementStyle(content, 'margin-bottom', this.mb) 44 | }); 45 | } 46 | 47 | queryElement(elem: HTMLElement, q: string): HTMLElement { 48 | return elem.querySelector(q); 49 | } 50 | 51 | ionViewWillUnload() { 52 | this.event.unsubscribe('hideTabs'); 53 | this.event.unsubscribe('showTabs'); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/pages/user-info/user-info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 用户信息 5 | 6 | 7 | 8 | 9 | 10 |
11 | 用户名 12 | JerryMissTom 13 |
14 |
15 | 联系方式 16 | 582486638@qq.com 17 |
18 |
19 | 20 |
21 | 22 |
23 | -------------------------------------------------------------------------------- /src/pages/user-info/user-info.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { IonicPageModule } from 'ionic-angular'; 3 | import { UserInfoPage } from './user-info'; 4 | 5 | @NgModule({ 6 | declarations: [ 7 | UserInfoPage, 8 | ], 9 | imports: [ 10 | IonicPageModule.forChild(UserInfoPage), 11 | ], 12 | }) 13 | export class UserInfoPageModule {} 14 | -------------------------------------------------------------------------------- /src/pages/user-info/user-info.scss: -------------------------------------------------------------------------------- 1 | page-user-info { 2 | .item { 3 | width: 100%; 4 | height: rem(50); 5 | padding: 0 rem(10); 6 | border-bottom: #ececec solid rem(1); 7 | } 8 | 9 | .login-out { 10 | width: 50%; 11 | height: rem(30); 12 | margin-top: rem(100); 13 | color: #488aff; 14 | font-size: 20px; 15 | border-radius: 5%; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/pages/user-info/user-info.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { IonicPage, NavController, NavParams } from 'ionic-angular'; 3 | import { App } from 'ionic-angular/components/app/app'; 4 | import { LoginComponent } from '../login/login'; 5 | 6 | @IonicPage() 7 | @Component({ 8 | selector: 'page-user-info', 9 | templateUrl: 'user-info.html', 10 | }) 11 | export class UserInfoPage { 12 | 13 | constructor(public navCtrl: NavController, 14 | public navParams: NavParams, 15 | private app: App) { 16 | } 17 | 18 | 19 | loginOut() { 20 | this.app.getRootNavs()[0].setRoot(LoginComponent); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check out https://googlechromelabs.github.io/sw-toolbox/ for 3 | * more info on how to use sw-toolbox to custom configure your service worker. 4 | */ 5 | 6 | 7 | 'use strict'; 8 | importScripts('./build/sw-toolbox.js'); 9 | 10 | self.toolbox.options.cache = { 11 | name: 'ionic-cache' 12 | }; 13 | 14 | // pre-cache our key assets 15 | self.toolbox.precache( 16 | [ 17 | './build/main.js', 18 | './build/vendor.js', 19 | './build/main.css', 20 | './build/polyfills.js', 21 | 'index.html', 22 | 'manifest.json' 23 | ] 24 | ); 25 | 26 | // dynamically cache any other local assets 27 | self.toolbox.router.any('/*', self.toolbox.fastest); 28 | 29 | // for any other requests go to the network, cache, 30 | // and then only use that cached resource if your user goes offline 31 | self.toolbox.router.default = self.toolbox.networkFirst; 32 | -------------------------------------------------------------------------------- /src/theme/variables.scss: -------------------------------------------------------------------------------- 1 | // 页面适配 2 | // 项目的中的所有单位均采用需调用 rem(视觉图的像素值) 方法计算相应的虚拟像素值 3 | $vm_fontsize: 36; // 是$vm_design 值得十分之一 4 | $vm_design: 360; // 根据需要替换成设计稿的值,比如设计稿给你的宽度是360px, 5 | @function rem($px) { 6 | @return ($px / $vm_fontsize) * 1rem; 7 | } 8 | 9 | $action-sheet-ios-button-font-size: rem(20); 10 | $action-sheet-ios-title-font-size: rem(13); 11 | $action-sheet-md-button-font-size: rem(16); 12 | $action-sheet-md-icon-font-size: rem(24); 13 | $action-sheet-md-title-font-size: rem(16); 14 | $action-sheet-wp-button-font-size: rem(15); 15 | $action-sheet-wp-icon-font-size: rem(24); 16 | $action-sheet-wp-title-font-size: rem(20); 17 | $badge-font-size: rem(13); 18 | $button-ios-font-size: rem(16); 19 | $button-ios-large-font-size: rem(20); 20 | $button-ios-small-font-size: rem(13); 21 | $button-ios-small-icon-font-size: rem(13); 22 | $button-md-font-size: rem(14); 23 | $button-md-large-font-size: rem(20); 24 | $button-md-small-font-size: rem(13); 25 | $button-md-small-icon-font-size: rem(14); 26 | $button-wp-font-size: rem(14); 27 | $button-wp-large-font-size: rem(20); 28 | $button-wp-small-font-size: rem(13); 29 | $button-wp-small-icon-font-size: rem(13); 30 | $card-ios-font-size: rem(14); 31 | $card-ios-header-font-size: rem(16); 32 | $card-ios-title-font-size: rem(18); 33 | $card-md-font-size: rem(14); 34 | $card-md-header-font-size: rem(16); 35 | $card-md-title-font-size: rem(24); 36 | $card-wp-font-size: rem(14); 37 | $card-wp-header-font-size: rem(16); 38 | $card-wp-title-font-size: rem(24); 39 | $font-size-base: rem(14); 40 | $font-size-ios-base: $font-size-base; 41 | $font-size-ios-base: $font-size-base; 42 | $font-size-md-base: $font-size-base; 43 | $font-size-md-base: $font-size-base; 44 | $font-size-wp-base: $font-size-base; 45 | $font-size-wp-base: $font-size-base; 46 | $h1-font-size: rem(26); 47 | $h2-font-size: rem(24); 48 | $h3-font-size: rem(22); 49 | $h4-font-size: rem(20); 50 | $h5-font-size: rem(18); 51 | $h6-font-size: rem(16); 52 | $item-ios-body-text-font-size: rem(17); 53 | $item-ios-paragraph-font-size: rem(14); 54 | $item-md-body-text-font-size: rem(14); 55 | $item-md-divider-font-size: $item-md-body-text-font-size; 56 | $item-md-font-size: rem(16); 57 | $item-wp-body-text-font-size: rem(14); 58 | $item-wp-divider-font-size: rem(20); 59 | $item-wp-font-size: rem(16); 60 | $list-ios-header-font-size: rem(12); 61 | $list-md-header-font-size: rem(14); 62 | $list-wp-header-font-size: rem(20); 63 | $searchbar-wp-input-font-size: rem(14); 64 | $segment-button-ios-font-size: rem(13); 65 | $segment-button-ios-toolbar-font-size: rem(12); 66 | $segment-button-md-font-size: rem(12); 67 | $segment-button-wp-font-size: rem(13); 68 | $tabs-md-tab-font-size: rem(12); 69 | $tabs-md-tab-font-size-active: rem(14); 70 | $tabs-wp-tab-font-size: rem(12); 71 | $toast-ios-title-font-size: rem(14); 72 | $toast-md-title-font-size: rem(15); 73 | $toast-wp-title-font-size: rem(14); 74 | $toolbar-ios-button-font-size: rem(17); 75 | $toolbar-ios-title-font-size: rem(17); 76 | $toolbar-md-button-font-size: rem(14); 77 | $toolbar-md-title-font-size: rem(20); 78 | $toolbar-wp-button-font-size: rem(14); 79 | $toolbar-wp-title-font-size: rem(15); 80 | $action-sheet-ios-button-min-height: rem(48); 81 | $action-sheet-ios-title-padding: rem(15); 82 | $action-sheet-md-button-min-height: rem(48); 83 | $action-sheet-md-icon-width: rem(23); 84 | $action-sheet-wp-button-height: rem(48); 85 | $action-sheet-wp-icon-width:rem(23); 86 | $alert-wp-input-line-height:rem(30); 87 | $button-ios-margin-bottom: rem(4); 88 | $button-ios-margin-end: rem(2); 89 | $button-ios-margin-start:rem(2); 90 | $button-ios-margin-top: rem(4); 91 | $button-md-height: rem(36); 92 | $button-md-margin-bottom: rem(4); 93 | $button-md-margin-end: rem(2); 94 | $button-md-margin-start:rem(2); 95 | $button-md-margin-top: rem(4); 96 | $button-round-padding-end: rem(26); 97 | $button-wp-height: rem(36); 98 | $button-wp-margin-bottom :rem(4); 99 | $button-wp-margin-end: rem(2); 100 | $button-wp-margin-start: rem(2); 101 | $button-wp-margin-top:rem(4); 102 | $list-ios-header-letter-spacing:rem(1); 103 | $list-md-header-min-height:rem(45); 104 | $searchbar-ios-input-height:rem(30); 105 | $searchbar-md-input-line-height:rem(30); 106 | $searchbar-wp-input-line-height:rem(30); 107 | $segment-button-ios-height: rem(32); 108 | $segment-button-ios-icon-line-height: rem(28); 109 | $segment-button-ios-icon-size: rem(26); 110 | $segment-button-ios-line-height:rem(30); 111 | $segment-button-ios-toolbar-button-height: rem(26); 112 | $segment-button-ios-toolbar-icon-line-height: rem(24); 113 | $segment-button-ios-toolbar-icon-size:rem(22); 114 | $segment-button-ios-toolbar-line-height: rem(25); 115 | $segment-button-md-font-size: rem(12); 116 | $segment-button-md-height: rem(42); 117 | $segment-button-md-icon-size: rem(26); 118 | $segment-button-md-line-height: rem(40); 119 | $segment-button-wp-height: rem(40); 120 | $segment-button-wp-icon-size: rem(26); 121 | $segment-button-wp-line-height: rem(40); 122 | $tabs-md-tab-font-size-active:rem(14); 123 | $tabs-md-tab-icon-size:rem(24); 124 | $tabs-md-tab-min-height:rem(46); 125 | $tabs-wp-tab-icon-size:rem(24); 126 | $text-input-wp-line-height:rem(30); 127 | $toast-ios-border-radius:rem(6.5); 128 | $toast-ios-title-padding-top:rem(15); 129 | $toast-wp-title-padding-top:rem(15); 130 | $segment-button-ios-icon-line-height:rem(28); 131 | $menu-width:rem(200); 132 | $menu-small-width:rem(200); 133 | 134 | 135 | // Ionic Variables and Theming. For more info, please see: 136 | // http://ionicframework.com/docs/theming/ 137 | // Font path is used to include ionicons, 138 | // roboto, and noto sans fonts 139 | $font-path: "../assets/fonts"; 140 | // The app direction is used to include 141 | // rtl styles in your app. For more info, please see: 142 | // http://ionicframework.com/docs/theming/rtl-support/ 143 | $app-direction: ltr; 144 | @import "ionic.globals"; 145 | // Shared Variables 146 | // -------------------------------------------------- 147 | // To customize the look and feel of this app, you can override 148 | // the Sass variables found in Ionic's source scss files. 149 | // To view all the possible Ionic variables, see: 150 | // http://ionicframework.com/docs/theming/overriding-ionic-variables/ 151 | // Named Color Variables 152 | // -------------------------------------------------- 153 | // Named colors makes it easy to reuse colors on various components. 154 | // It's highly recommended to change the default colors 155 | // to match your app's branding. Ionic uses a Sass map of 156 | // colors so you can add, rename and remove colors as needed. 157 | // The "primary" color is the only required color in the map. 158 | $colors: ( primary: #488aff, secondary: #32db64, danger: #f53d3d, light: #f4f4f4, dark: #222); 159 | // App iOS Variables 160 | // -------------------------------------------------- 161 | // iOS only Sass variables can go here 162 | // App Material Design Variables 163 | // -------------------------------------------------- 164 | // Material Design only Sass variables can go here 165 | // App Windows Variables 166 | // -------------------------------------------------- 167 | // Windows only Sass variables can go here 168 | // App Theme 169 | // -------------------------------------------------- 170 | // Ionic apps can have different themes applied, which can 171 | // then be future customized. This import comes last 172 | // so that the above variables are used and Ionic's 173 | // default are overridden. 174 | @import "ionic.theme.default"; 175 | // Ionicons 176 | // -------------------------------------------------- 177 | // The premium icon font for Ionic. For more info, please see: 178 | // http://ionicframework.com/docs/ionicons/ 179 | @import "ionic.ionicons"; 180 | // Fonts 181 | // -------------------------------------------------- 182 | @import "roboto"; 183 | @import "noto-sans"; 184 | 185 | 186 | 187 | //--------------------------自定义字体示例------------------------ 188 | // 把字体文件放在asset中,然后引入 189 | // @font-face { 190 | // font-family: 'Sans'; 191 | // src: url('../assets/fonts/Sans.otf') format('opentype'); 192 | // } 193 | 194 | 195 | //-------------------------自定义tab图标示例------------------------- 196 | // 修改Tab的图标和颜色 197 | // $iconfont-path: "../assets/fonts"; 198 | // @font-face { 199 | // font-family: "iconfont"; 200 | // src: url('iconfont.eot?t=1514257834808'); 201 | // /* IE9*/ 202 | // src: url('iconfont.eot?t=1514257834808#iefix') format('embedded-opentype'), /* IE6-IE8 */ 203 | // url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAuQAAsAAAAAEFQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAAQwAAAFZW7kgkY21hcAAAAYAAAACHAAAB4mM80tBnbHlmAAACCAAAB0AAAAl03fTStGhlYWQAAAlIAAAAMQAAADYQkwFwaGhlYQAACXwAAAAgAAAAJAiDBExobXR4AAAJnAAAABsAAAAkJNb//GxvY2EAAAm4AAAAFAAAABQIGAnqbWF4cAAACcwAAAAfAAAAIAEbAO9uYW1lAAAJ7AAAAUUAAAJtPlT+fXBvc3QAAAs0AAAAWgAAAH3UQ2QFeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2BkkWCcwMDKwMHUyXSGgYGhH0IzvmYwYuRgYGBiYGVmwAoC0lxTGBwYKp6JMTf8b2CIYW5haAAKM4LkANzPC6cAeJzFkdENgzAMRM+QAgJa+IEpGKID9QP1i4lvDXq2+ekEXPQS20rk6AzgAaAWmyiAfWFwfVS1qNfoo17wVt5pVToPTlzPM6KBS0QuixtzRJXeFnVo0KoGa3Cb7L7W/xpj369MruC40Bc5JO4wx8Snw2fiE+Ir8clxSuQwuCTyGlwTdD9DdRo5AHicbVZbbBxXGT6XmTkzuzNndmZ2Znb2MuvZ9e7aXmcX73ovie11NhcLTCqndktt2jSJUQIlIgmXNIpUQVWBUjUVsoAUEUpAqNAXhFRQHxpF5IG26gtCFQ88FAkKRiJC7UNVNX2IJ/wztkuEODvnP//555zzf+fM980sEhG69y69STPIQmNoCh1CRxHCUh2XOCngoDbdIHVsB6LtpjmtlWsBK5cadA67JSnttLrTVVdiko459nE7aHVrDVLDnekBmcEtp4Cxl8uumJW8STdwIlPzvxMukp9ju1jO64M94Wcm59OtEUu+qJqmZ5rPy5IoyoQIOsdfcR1FVBJS+JKoZ+2bxXFSxKpXyx5Z00Zy5slnp88WKq6C8dNPYys3wl+eN7IGXE9lHcv0WEqTM1mtPJrGFzeTGUstVP+BoMiw15/RP9MxRBFDSaTDnl00jjoIWUZg0HKn3dtp8W5bG+Bet1qrwi4dt9XtuZUBdn3MOK418AK+fmxz85XY3v1D3JClIdcFfGp5+asiObU8MusNw/fEmfpknwiz9fpeOhaexD8Nf7f5+E4bXgjX8fXw1uY91Leb3vJ5iZxeBqubc3+D4duThNkIvwT4fysguoZm0afRCjqOzqBz8LQ4dtOOCw+G1TqN3V4jwghIewNcm67Weu0IPMf2dqSBITLADYxL1WiLPnYdyWrE2/WJ5EJ0uhtFObbuG4EDO6DHGjM0yTaUXHpBGD6+D/wrSYc391Fh2AQrCldd3U/OCVgcNpr7CE4lr2Q6c2x49yM7K2DXtHOUuh/v+pL7JwhkzLj/zn9HZO9eo+/dtejnYBWe57d532rNsGGTZ5O/hxzbucAyU347KU8zk0Eucdg0Svyv8sFj3a3Uzpom8PBkvCh0RgsvZwxnJwn+XsaIozBka2kNRVr4Nf0nvbjDjwroAVVgy7u/6IA4ZvGxMDi+Xstxe/GhVbZjsU9+hfvhW7v1i/Tak09eo3h//7mb7nr+3Z9Mn5poZ6Yy/f3h+0tPEPLEUmw/XKnCj7wKQ2HCwsVa850fvHCLZr2HNCtRu7C1Ow4soAPNAg/mkY3qoFiEt3GUAUHasWvM7VU7AyzWmGNDCJ4fQI7gAg9c3O60O+W49moMxtplux1Vwr220x99cOLGHUHg7cv9CfYGeRYa4c3vx3eO1m98JAqYh9X+FSjPTJz/xsQ3r0Ih/2ZsgXPxzg2jbPLhueEDn7/2xl+i5oXXKZMOcy7cuWGWDR6+fqn9UJv/qHr5cnXDBRfBOaN7P6Z36FmkIQP246ECCuDkkULcntE2KiIYAG0D5O3q3tfSO6EQ8n6wiof4s8dGttZW4/LqGpRX1tbwh/hSeHUxv/UWuXT7g60NMuGGi6v/Wv1g7W2w/VXQlHgvvHdd+CX9NvoCuoCeQb9Bf4dgpHjQSDPSSmceDyKvG0X0mABSMRZX2ikSCWoUifq1arfXhRm9aDb4VfDdthsphznwAomI40BXx72KnXbmodftdeJFq1LEox4DmUUqFf/fUtGNndTbibGdluLMu3jnPsFbjQDHKo+z+xHCT/Iz+j6tHzlwaLyTUOycS9UU0VRBlUxznBRy/kphzBE1QaFK0iZYz+sEiD538IEJuk4HX5/tZovCGC8nJFXJ7D/0kprLubO5g3k3ERhlrajtnf/avHByauuWKh8/zpIYJ9mJEyx5drBI9+bz9MTRybGFrTenSGk+KOomcZktUVnS/OxhT9SnzbRKJMqoqmKspGQ/N1qezAiHcGayEuR9OaXgpEolQSJq2pzWRW/BK2qiIkg2c4mpB8X5ElmXT435e4pnSjmvNEf1JM9bhtd/0DYlTMZpodR+zHHEHBc1xj3SLOiZ2dPBWHH8tCirL87lR1Mtf88MzO+a31pZDOg4cQtHflhfGd03Ve4q1cLci6os3D4gy8T1iCIfZArxwGEkEJZqY8wrP2IZs6L0cElPJ3wjV+IZ01cOTAZZMoUNp9BKJoUUl5hGfIOpQc9yU+4MFfa5hmP2g4Ri+ERjEtdFRWsVHANPkWwweUDxzQwv5Qw/YfPSwxLa4e0vhAn6ZbQEX4JH0KNoA4JBrxqzBq5G9JK/j4Lw2IGD5Zgf3Sb5XzpLaaBTaYdTnLLAFgMjwFAjnUV8hGlAyXjZmJFxIvgbAPyLOWlHk2NW7ugBfxweF4Te6UzLM9MUroAlrf7MdxN5z2k7RV3TR4UzuiSoXJJVIUF1nsN5OzuwKmlBZrqHFTvVGMvP9soqrpA9W38kU2ELnwmvPvraa1tPtUixm9XVjKgmqJoglAlSQnUHrsDrmkIY0FfETANgCs45xeKoZXeV53pq3tRKlrMnNXJ05Pzi4YBWiJUprg+PPEbcKjZUjVspuz5MJQkWAsnLVRZtI1FIGAXfMtKd1YJZ9Er6lxaIES7jhXzrnCAtFjWmaCNaLqGYUiqTyH/K8m0ypZuJwNJUmhAYllX4OMhqoZVKa3YT/QcP3Jg3eJxjYGRgYABiiam74uP5bb4ycLMwgMC19HurYPT/f/9nsyxjbgFyORiYQKIAZDsN0wAAAHicY2BkYGBu+N/AEMNy+P+///9ZljEARVAAJwC/+wfWeJxjYWBgYH7JwMDCgAUf/v+PRfP/PwAyxwXzAAAAAAAAdgDWAYYB2gJAAoAD3AS6eJxjYGRgYOBkeMzAwQACTEDMBYQMDP/BfAYAICACCwB4nGWPTU7DMBCFX/oHpBKqqGCH5AViASj9EatuWFRq911036ZOmyqJI8et1ANwHo7ACTgC3IA78EgnmzaWx9+8eWNPANzgBx6O3y33kT1cMjtyDRe4F65TfxBukF+Em2jjVbhF/U3YxzOmwm10YXmD17hi9oR3YQ8dfAjXcI1P4Tr1L+EG+Vu4iTv8CrfQ8erCPuZeV7iNRy/2x1YvnF6p5UHFockikzm/gple75KFrdLqnGtbxCZTg6BfSVOdaVvdU+zXQ+ciFVmTqgmrOkmMyq3Z6tAFG+fyUa8XiR6EJuVYY/62xgKOcQWFJQ6MMUIYZIjK6Og7VWb0r7FDwl57Vj3N53RbFNT/c4UBAvTPXFO6stJ5Ok+BPV8bUnV0K27LnpQ0kV7NSRKyQl7WtlRC6gE2ZVeOEXpc0Yk/KGdI/wAJWm7IAAAAeJxtikEKgDAMBLNqa+3VF6YiaaqkByno7xV6dWAPswwN1In0z4IBIyY4eMwIWBAJtxfWk21OXJNyDUVNnm++fPaoO9rWLB57btLYTl2l9uDKbNI/ohfDuxpuAAA=') format('woff'), url('iconfont.ttf?t=1514257834808') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ 204 | // url('iconfont.svg?t=1514257834808#iconfont') format('svg'); 205 | // /* iOS 4.1- */ 206 | // } 207 | 208 | // .iconfont { 209 | // font-family: "iconfont" !important; 210 | // font-size: rem(24); 211 | // font-style: normal; 212 | // -webkit-font-smoothing: antialiased; 213 | // -moz-osx-font-smoothing: grayscale; 214 | // } 215 | 216 | // .icon-home:before { 217 | // content: "\e60a"; 218 | // } 219 | 220 | // .icon-contact:before { 221 | // content: "\e60b"; 222 | // } 223 | 224 | // .icon-about:before { 225 | // content: "\e60c"; 226 | // } 227 | 228 | // .ion-md-custom-home:before, 229 | // .ion-ios-custom-home:before, 230 | // .ion-ios-custom-home-outline:before, 231 | // .ion-md-custom-contact:before, 232 | // .ion-ios-custom-contact:before, 233 | // .ion-ios-custom-contact-outline:before, 234 | // .ion-md-custom-about:before, 235 | // .ion-ios-custom-about:before, 236 | // .ion-ios-custom-about-outline:before, 237 | // { 238 | // @extend .iconfont; 239 | // } 240 | 241 | // .ion-ios-custom-home:before { 242 | // content: "\e60a"; 243 | // } 244 | 245 | // .ion-ios-custom-home-outline:before { 246 | // content: "\e60a"; 247 | // } 248 | 249 | // .ion-ios-custom-contact:before { 250 | // content: "\e60b"; 251 | // } 252 | 253 | // .ion-ios-custom-contact-outline:before { 254 | // content: "\e60b"; 255 | // } 256 | 257 | // .ion-ios-custom-about:before { 258 | // content: "\e60c"; 259 | // } 260 | 261 | // .ion-ios-custom-about-outline:before { 262 | // content: "\e60c"; 263 | // } 264 | 265 | // // 修改Tab点击选中颜色 266 | // $tabs-ios-tab-text-color-active:#F37021; 267 | // $tabs-ios-tab-icon-color-active:#F37021; 268 | // $tabs-md-tab-text-color-active:#F37021; 269 | // $tabs-md-tab-icon-color-active:#F37021; 270 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "lib": [ 8 | "dom", 9 | "es2015" 10 | ], 11 | "module": "es2015", 12 | "moduleResolution": "node", 13 | "sourceMap": true, 14 | "target": "es5" 15 | }, 16 | "include": [ 17 | "src/**/*.ts" 18 | ], 19 | "exclude": [ 20 | "node_modules" 21 | ], 22 | "compileOnSave": false, 23 | "atom": { 24 | "rewriteTsconfig": false 25 | } 26 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-duplicate-variable": true, 4 | "no-unused-variable": [ 5 | true 6 | ] 7 | }, 8 | "rulesDirectory": [ 9 | "node_modules/tslint-eslint-rules/dist/rules" 10 | ] 11 | } 12 | --------------------------------------------------------------------------------