├── .editorconfig ├── .gitignore ├── README.md ├── config.xml ├── ionic.config.json ├── package.json ├── resources ├── 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-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~iphone.png └── splash.png ├── src ├── app │ ├── app.component.ts │ ├── app.config.ts │ ├── app.html │ ├── app.module.ts │ ├── app.scss │ ├── index.html │ └── main.ts ├── assets │ ├── icon │ │ └── favicon.ico │ ├── img │ │ └── pwd_keyboard.png │ └── js │ │ ├── jquery-1.7.2.js │ │ ├── mui.min.js │ │ ├── mui.previewimage.js │ │ └── mui.zoom.js ├── components │ ├── component-demo │ │ ├── component-demo.html │ │ ├── component-demo.scss │ │ └── component-demo.ts │ ├── components.module.ts │ ├── map-position-picker │ │ ├── map-position-picker.html │ │ ├── map-position-picker.scss │ │ └── map-position-picker.ts │ └── previewimg │ │ ├── previewimg.html │ │ ├── previewimg.scss │ │ └── previewimg.ts ├── index.html ├── manifest.json ├── model │ ├── mapPositionModel.ts │ └── share.ts ├── pages │ ├── baidu-map │ │ ├── baidu-map.html │ │ ├── baidu-map.module.ts │ │ ├── baidu-map.scss │ │ └── baidu-map.ts │ ├── browser │ │ ├── browser-popover.module.ts │ │ ├── browser-popover.ts │ │ ├── browser.html │ │ ├── browser.module.ts │ │ ├── browser.scss │ │ └── browser.ts │ ├── gaodemap │ │ ├── gaodemap.html │ │ ├── gaodemap.module.ts │ │ ├── gaodemap.scss │ │ └── gaodemap.ts │ ├── index │ │ ├── index.html │ │ ├── index.module.ts │ │ ├── index.scss │ │ └── index.ts │ ├── page-demo │ │ ├── page-demo.html │ │ ├── page-demo.module.ts │ │ ├── page-demo.scss │ │ └── page-demo.ts │ └── tabs │ │ ├── tabs.html │ │ └── tabs.ts ├── pipes │ ├── pipe-demo │ │ └── pipe-demo.ts │ └── pipes.module.ts ├── providers │ ├── geolocation │ │ └── geolocation.ts │ ├── http-ser │ │ └── http-ser.ts │ ├── interface-list │ │ └── interface-list.ts │ └── pop-ser │ │ └── pop-ser.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 | This is a starter template for [Ionic](http://ionicframework.com/docs/) projects. 2 | 3 | ## How to use this template 4 | 5 | *This template does not work on its own*. The shared files for each starter are found in the [ionic2-app-base repo](https://github.com/ionic-team/ionic2-app-base). 6 | 7 | To use this template, either create a new ionic project using the ionic node.js utility, or copy the files from this repository into the [Starter App Base](https://github.com/ionic-team/ionic2-app-base). 8 | 9 | ### With the Ionic CLI: 10 | 11 | Take the name after `ionic2-starter-`, and that is the name of the template to be used when using the `ionic start` command below: 12 | 13 | ```bash 14 | $ sudo npm install -g ionic cordova 15 | $ ionic start myTabs tabs 16 | ``` 17 | 18 | Then, to run it, cd into `myTabs` and run: 19 | 20 | ```bash 21 | $ ionic cordova platform add ios 22 | $ ionic cordova run ios 23 | ``` 24 | 25 | Substitute ios for android if not on a Mac. 26 | 27 | #### 项目概况 28 | - 所有的http请求底层封装在http-ser的provider中 29 | - http没有进行加密。。。 30 | - 所有的请求没有使用angular默认的 RxJS Observabl,转为更通用的promise来进行链式操作 31 | - 所有的接口统一写在interface-list的provider中,便于集中管理 32 | - 全局变量统一写在app.config.ts中 33 | - 组件demo,pipedemo,providerdemo都有,可以参考 34 | - 可以在根组件添加全局安卓物理返回键箭头 35 | 36 | 37 | #### 常见命令 38 | ionic help 39 | ionic info 40 | 41 | ionic start appName 42 | 43 | npm install --save-dev --save-exact @ionic/cli-plugin-ionic-angular@latest 44 | npm install --save-dev --save-exact @ionic/cli-plugin-cordova@latest 45 | 46 | ionic g page YourPageName //创建新页面 47 | ionic g directive YourPageName //创建指令 48 | ionic g component YourComponentName //创建组件 49 | ionic g provider YourProviderName //创建服务 50 | ionic g pipe YourPipeName //创建过滤器 51 | 52 | ionic serve 53 | ionic build 54 | ionic cordova plugins 55 | ionic cordova emulate 56 | ionic cordova run 57 | ionic cordova add platform android 58 | ionic cordova remove platform android 59 | ionic cordova build android --prod --release 60 | 61 | #### 初始化项目步骤 62 | 1.项目需要进行http请求,以及双向绑定,需要在app.module.ts引入下面核心包 63 | import { BrowserModule } from '@angular/platform-browser'; 64 | import { HttpModule} from '@angular/http'; 65 | 2.加入到app.module.ts的imports数组中 66 | BrowserModule, 67 | HttpModule, 68 | 3.封装http请求,转为promise 69 | 在封装的http-ser,provider中引入toPromise的raxjs, 70 | import 'rxjs/add/operator/map'; 71 | import 'rxjs/add/operator/toPromise'; 72 | 然后在请求后 73 | http.get().toPromise() 74 | 4.项目的全局配置在app.module.ts的imports数组中的 IonicModule.forRoot的第二个参数 75 | IonicModule.forRoot(MyApp,{ 76 | 77 | }) 78 | 4.使用自定义组件component 79 | - 1.由于现在组件也是懒加载,有自己的module.ts文件,所以可以不用在全局app.module.ts加入,用到在加载 80 | - 2.在需要使用组件的页面的module.ts文件中引入组件并加入imports数组, 81 | - 3.即可使用 82 | 5.pipe与组件同理 83 | 6.provider是在app.module.ts全局加入providers数组中 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MyApp 4 | An awesome Ionic/Cordova app. 5 | Ionic Framework Team 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 | 88 | -------------------------------------------------------------------------------- /ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "base-app", 3 | "app_id": "", 4 | "type": "ionic-angular", 5 | "integrations": { 6 | "cordova": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "base-app", 3 | "version": "0.0.1", 4 | "author": "Ionic Framework", 5 | "homepage": "http://ionicframework.com/", 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": "4.1.3", 16 | "@angular/compiler": "4.1.3", 17 | "@angular/compiler-cli": "4.1.3", 18 | "@angular/core": "4.1.3", 19 | "@angular/forms": "4.1.3", 20 | "@angular/http": "4.1.3", 21 | "@angular/platform-browser": "4.1.3", 22 | "@angular/platform-browser-dynamic": "4.1.3", 23 | "@ionic-native/core": "3.12.1", 24 | "@ionic-native/splash-screen": "3.12.1", 25 | "@ionic-native/status-bar": "3.12.1", 26 | "@ionic/storage": "2.0.1", 27 | "cordova-android": "^6.2.3", 28 | "cordova-plugin-console": "^1.0.5", 29 | "cordova-plugin-device": "^1.1.4", 30 | "cordova-plugin-splashscreen": "^4.0.3", 31 | "cordova-plugin-statusbar": "^2.2.2", 32 | "cordova-plugin-whitelist": "^1.3.1", 33 | "ionic-angular": "3.6.1", 34 | "ionic-plugin-keyboard": "^2.2.1", 35 | "ionicons": "3.0.0", 36 | "rxjs": "5.4.0", 37 | "sw-toolbox": "3.6.0", 38 | "zone.js": "0.8.12" 39 | }, 40 | "devDependencies": { 41 | "@ionic/app-scripts": "2.1.4", 42 | "typescript": "2.3.4" 43 | }, 44 | "description": "An Ionic project", 45 | "cordova": { 46 | "plugins": { 47 | "cordova-plugin-console": {}, 48 | "cordova-plugin-device": {}, 49 | "cordova-plugin-splashscreen": {}, 50 | "cordova-plugin-statusbar": {}, 51 | "cordova-plugin-whitelist": {}, 52 | "ionic-plugin-keyboard": {} 53 | }, 54 | "platforms": [ 55 | "android" 56 | ] 57 | } 58 | } -------------------------------------------------------------------------------- /resources/android/icon/drawable-hdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/icon/drawable-hdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-ldpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/icon/drawable-ldpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-mdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/icon/drawable-mdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-xhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/icon/drawable-xhdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-xxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/icon/drawable-xxhdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-xxxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/icon/drawable-xxxhdpi-icon.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-land-hdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-land-ldpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-land-mdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-land-xhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-land-xxhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-land-xxxhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-port-hdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-port-ldpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-port-mdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-port-xhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-port-xxhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/android/splash/drawable-port-xxxhdpi-screen.png -------------------------------------------------------------------------------- /resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/icon.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-40.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-40@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-40@3x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-50.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-50@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-60.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-60@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-60@3x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-72.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-72@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-76.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-76@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-83.5@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-small.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-small@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon-small@3x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon.png -------------------------------------------------------------------------------- /resources/ios/icon/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/icon/icon@2x.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-568h@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-568h@2x~iphone.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-667h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-667h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-736h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-Landscape-736h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-Landscape@2x~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape@~ipadpro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-Landscape@~ipadpro.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-Landscape~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-Portrait@2x~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait@~ipadpro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-Portrait@~ipadpro.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default-Portrait~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default@2x~iphone.png -------------------------------------------------------------------------------- /resources/ios/splash/Default~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/resources/ios/splash/Default~iphone.png -------------------------------------------------------------------------------- /resources/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/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 | 8 | @Component({ 9 | templateUrl: 'app.html' 10 | }) 11 | export class MyApp { 12 | rootPage:any = TabsPage; 13 | 14 | constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) { 15 | platform.ready().then(() => { 16 | // Okay, so the platform is ready and our plugins are available. 17 | // Here you can do any higher level native things you might need. 18 | statusBar.styleDefault(); 19 | splashScreen.hide(); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 请求地址头 3 | */ 4 | // 测试环境 5 | // export const APP_SERVE_URL:string = 'http://192.168.1.88/v1'; 6 | // export const APP_SERVE_URL:string = 'http://kmf.dev.ipvp.cn/v1'; 7 | // 生产环境 8 | export const APP_SERVE_URL:string = 'http://118.190.150.148:9001/jfsc'; 9 | //AES加密key 10 | export const AES_key:string =")O[NB]6,YF}+efcaj{+oESb9d8>Z'e9M"; 11 | /** 12 | * App配置信息 13 | */ 14 | export class AppConfig { 15 | static PCmodel:boolean = false; //PC端调试模式 16 | static Appmodel:number=3; //1首次启动 2.今日首次启动 3普通模式启动 17 | //设备信息 18 | static deviceId:string = ''; //设备id 19 | static deviceCordova:string = ''; //设备上运行的Cordova版本 20 | static deviceModel:string = ''; //设备型号或产品的名称 21 | static devicePlatform:string = ''; //操作系统名称 22 | static devicePlatformVersion:string = ''; //操作系统版本 23 | static deviceManufacturer:string = ''; //设备的制造商 24 | static deviceSerial:string = ''; //设备硬件序列号 25 | //APP信息 26 | static platform:string = ''; // android ios 27 | static appName:string = 'CRM_KmfApp'; //CRM_KmfApp 28 | static appVersion:string = '2.0.2'; //版本号 2.0.2 29 | //常规配置 30 | static userProtocol:string = ''; //用户协议 31 | //导购用户信息 32 | static userName:string = ''; //账号名 33 | static token:string = ''; //token 34 | static userInfo:any = {}; //用户信息 35 | //导购配置信息 36 | static callingType:number = 2; //通话方式 [1,2,3] 1免费 2普通 3两者 37 | static inited:boolean=true; //系统是否可用 (指该执行人员归属的数据是否准备完毕) 38 | static balanceMinute:number = 0; //剩余通话分钟数 39 | static showCustomerPhone:boolean=false; //是否显示会员电话号码(导购可见) 40 | //授权信息 41 | static expireDate:any = '2018.01.01'; //APP到期日期 42 | //极光推送 43 | static jPushRegistrationId:string=''; //极光的注册id; 44 | static jPushAlias:string=''; //极光的别名; 45 | static jPushTags:string=''; //极光的标签; 46 | 47 | 48 | //获取设备高度 49 | public static getWindowHeight() { 50 | return window.screen.height; 51 | } 52 | 53 | //获取设备宽度 54 | public static getWindowWidth() { 55 | return window.screen.width; 56 | } 57 | 58 | //获取设备屏幕分辨率 59 | public static getFenbianlv() { 60 | let x=window.screen.width * window.devicePixelRatio; 61 | let y=window.screen.height * window.devicePixelRatio; 62 | return [x,y]; 63 | } 64 | //获取通话方式 65 | public static getCallingType():number { 66 | return this.callingType ; 67 | } 68 | 69 | //获取系统是否可用 不可用返回false 70 | public static getInited():boolean { 71 | return this.inited; 72 | } 73 | 74 | //获取剩余通话分钟数 75 | public static getBalanceMinute():number { 76 | return this.balanceMinute ; 77 | } 78 | 79 | //获取本地时间 格式:2017-01-03 80 | public static getLocalTime() { 81 | let date = new Date(); 82 | let month:any = date.getMonth() + 1; 83 | let strDate:any = date.getDate(); 84 | if (month >= 1 && month <= 9) { 85 | month = "0" + month; 86 | } 87 | if (strDate >= 0 && strDate <= 9) { 88 | strDate = "0" + strDate; 89 | } 90 | let dd:string = date.getFullYear() + "-" + month + "-" + strDate; 91 | return dd; 92 | } 93 | 94 | //获取本地时间 格式:20170103 95 | public static getLocalTime2() { 96 | let date = new Date(); 97 | let month:any = date.getMonth() + 1; 98 | let strDate:any = date.getDate(); 99 | if (month >= 1 && month <= 9) { 100 | month = "0" + month; 101 | } 102 | if (strDate >= 0 && strDate <= 9) { 103 | strDate = "0" + strDate; 104 | } 105 | let dd:string = date.getFullYear() + "" + month + "" + strDate; 106 | return dd; 107 | } 108 | 109 | //判断系统是否到期 超期返回true 110 | public static getIsExpired():boolean { 111 | if(!this.expireDate){ 112 | return true; 113 | } 114 | var DateTwo = this.expireDate; 115 | var myDate = new Date(); 116 | var DateOne = myDate.toLocaleDateString(); 117 | var TwoMonth = DateTwo.substring(5, 7); 118 | var TwoDay = DateTwo.substring(8, 10); 119 | var TwoYear = DateTwo.substring(0, 4); 120 | var cha = ((Date.parse(TwoMonth + '/' + TwoDay + '/' + TwoYear) - Date.parse(DateOne)) / 86400000); 121 | return (cha < 0) ? true : false; 122 | } 123 | 124 | //获取token 125 | public static getToken():string { 126 | return this.token || ''; 127 | } 128 | 129 | //获取平台 ios android none(小写) 130 | public static getPlatform():string { 131 | return this.platform || ''; 132 | } 133 | 134 | //获取设备id 135 | public static getDeviceid():string { 136 | return this.deviceId || ''; 137 | } 138 | 139 | //获取App名称 140 | public static getAppName():string { 141 | return this.appName || ''; 142 | } 143 | 144 | //获取App版本号 数字 2000001 145 | public static getAppVersion():any { 146 | let version = this.appVersion || ''; 147 | let t:any = version.split('.'); 148 | let num:number = parseInt(t[0]) * 1000000 + parseInt(t[1]) * 1000 + parseInt(t[2]); 149 | return num || ''; 150 | } 151 | 152 | //获取账号 153 | public static getuserName():string { 154 | return this.userName || ''; 155 | } 156 | 157 | //获取用户信息 158 | public static getUserInfo() { 159 | let userInfo = { 160 | userId: 0, //用户Id 161 | uuid: 0, //全局用户Id 162 | userName: '', 163 | token: '', 164 | orgId: 0, //会员组织机构Id 165 | name: '', //会员名称 166 | mobile: '' //执行人员的联系方式 167 | }; 168 | return this.userInfo || userInfo; 169 | } 170 | 171 | //去字符串两侧空格 172 | public static trim(str) { 173 | return str.replace(/(^s*)|(s*$)/g, ""); 174 | } 175 | 176 | public static getTestCount(){ 177 | let x=Math.floor((Math.random()*4)); 178 | let cc:any={ 179 | name:'测试号:谢大见', 180 | number:'18558756920', 181 | }; 182 | if(x===0){ 183 | cc={ 184 | name:'测试号0:赵', 185 | number:'15306907390', 186 | } 187 | }else if (x==1){ 188 | cc={ 189 | name:'测试号1:林', 190 | number:'13459202232', 191 | } 192 | }else if (x==2){ 193 | cc={ 194 | name:'测试号2:袁', 195 | number:'18221612515', 196 | } 197 | }else if (x==3){ 198 | cc={ 199 | name:'测试号3:詹', 200 | number:'18250347781', 201 | } 202 | }else if (x==4){ 203 | cc={ 204 | name:'测试号4:阳阳', 205 | number:'15060067536', 206 | } 207 | } 208 | return cc; 209 | } 210 | 211 | //正则,不能输入表情 212 | public static RegExp(str,event) { 213 | let regex=/[^\a-zA-Z0-9\u4E00-\u9FA5]/g; 214 | if(regex.test(str)){ 215 | str = str.replace(regex, ""); 216 | event.target.value=str;//显示文本替换掉 217 | return false; 218 | } 219 | } 220 | 221 | // 正则,不能输入表情和中文 222 | public static RegExpCn(str) { 223 | let regex=/[^\a-zA-Z0-9\|\$\(\)\*\+\.\[\]\?\\\/\^\{\}\-~`!@#%&_=,<>;:'"]/g; 224 | if(regex.test(str)){ 225 | // str = str.replace(regex, ""); 226 | // event.target.value=str;//显示文本替换掉 227 | return true; 228 | } 229 | } 230 | 231 | 232 | } 233 | 234 | -------------------------------------------------------------------------------- /src/app/app.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | //引入核心依赖 2 | import {NgModule, ErrorHandler} from '@angular/core'; 3 | import {IonicApp, IonicModule, IonicErrorHandler} from 'ionic-angular'; 4 | //引入双向绑定,http请求依赖 5 | import {BrowserModule} from '@angular/platform-browser'; 6 | import {HttpModule} from '@angular/http'; 7 | 8 | //引入页面组件 9 | import {MyApp} from './app.component'; 10 | import {TabsPage} from '../pages/tabs/tabs'; 11 | 12 | //引入native 13 | import {StatusBar} from '@ionic-native/status-bar'; 14 | import {SplashScreen} from '@ionic-native/splash-screen'; 15 | 16 | //引入自定义provider 17 | import {HttpSerProvider} from '../providers/http-ser/http-ser'; 18 | import {PopSerProvider} from '../providers/pop-ser/pop-ser'; 19 | import {InterfaceListProvider} from '../providers/interface-list/interface-list'; 20 | import {GeolocationProvider} from '../providers/geolocation/geolocation'; 21 | 22 | //引入自定义组件component (也可以不全局引入,在需要的页面引入需要的组件) 23 | import {ComponentsModule} from '../components/components.module'; 24 | 25 | //引入自定义过滤器pipe (也可以不全局引入,在需要的页面引入需要的pipe) 26 | 27 | 28 | @NgModule({ 29 | declarations: [ 30 | MyApp, 31 | TabsPage, 32 | ], 33 | imports: [ 34 | BrowserModule, 35 | HttpModule, 36 | ComponentsModule, 37 | //第二个参数是个对象,表示全局配置 38 | IonicModule.forRoot(MyApp) 39 | ], 40 | bootstrap: [IonicApp], 41 | entryComponents: [ 42 | MyApp, 43 | TabsPage 44 | ], 45 | providers: [ 46 | StatusBar, 47 | SplashScreen, 48 | // {provide: ErrorHandler, useClass: IonicErrorHandler}, 49 | HttpSerProvider, 50 | PopSerProvider, 51 | InterfaceListProvider, 52 | GeolocationProvider 53 | ] 54 | }) 55 | export class AppModule { 56 | } 57 | -------------------------------------------------------------------------------- /src/app/app.scss: -------------------------------------------------------------------------------- 1 | // http://ionicframework.com/docs/theming/ 2 | 3 | 4 | // App Global Sass 5 | // -------------------------------------------------- 6 | // Put style rules here that you want to apply globally. These 7 | // styles are for the entire app and not just one component. 8 | // Additionally, this file can be also used as an entry point 9 | // to import other Sass files to be included in the output CSS. 10 | // 11 | // Shared Sass variables, which can be used to adjust Ionic's 12 | // default Sass variables, belong in "theme/variables.scss". 13 | // 14 | // To declare rules for a specific mode, create a child rule 15 | // for the .md, .ios, or .wp mode classes. The mode class is 16 | // automatically applied to the element in the app. 17 | -------------------------------------------------------------------------------- /src/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |

点击这个按钮,获得您的坐标:

9 | 10 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /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/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/src/assets/icon/favicon.ico -------------------------------------------------------------------------------- /src/assets/img/pwd_keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiedajian/ionic3/6b5b14ab03f3210571a279f9c1908fcd1de1f546/src/assets/img/pwd_keyboard.png -------------------------------------------------------------------------------- /src/assets/js/mui.previewimage.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | 3 | var template = '
{{header}}
'; 4 | var itemTemplate = '
'; 5 | var defaultGroupName = '__DEFAULT'; 6 | var div = document.createElement('div'); 7 | var imgId = 0; 8 | var PreviewImage = function(options) { 9 | this.options = $.extend(true, { 10 | id: '__MUI_PREVIEWIMAGE', 11 | zoom: true, 12 | header: '', 13 | footer: '' 14 | }, options || {}); 15 | this.init(); 16 | this.initEvent(); 17 | }; 18 | var proto = PreviewImage.prototype; 19 | proto.init = function() { 20 | var options = this.options; 21 | var el = document.getElementById(this.options.id); 22 | if (!el) { 23 | div.innerHTML = template.replace(/\{\{id\}\}/g, this.options.id).replace('{{header}}', options.header).replace('{{footer}}', options.footer); 24 | document.body.appendChild(div.firstElementChild); 25 | el = document.getElementById(this.options.id); 26 | } 27 | 28 | this.element = el; 29 | this.scroller = this.element.querySelector($.classSelector('.slider-group')); 30 | this.indicator = this.element.querySelector($.classSelector('.preview-indicator')); 31 | this.loader = this.element.querySelector($.classSelector('.preview-loading')); 32 | if (options.footer) { 33 | this.element.querySelector($.classSelector('.preview-footer')).classList.remove($.className('hidden')); 34 | } 35 | this.addImages(); 36 | }; 37 | proto.initEvent = function() { 38 | var self = this; 39 | $(document.body).on('tap', 'img[data-preview-src]', function() { 40 | self.open(this); 41 | return false; 42 | }); 43 | var laterClose = null; 44 | var laterCloseEvent = function() { 45 | !laterClose && (laterClose = $.later(function() { 46 | self.loader.removeEventListener('tap', laterCloseEvent); 47 | self.scroller.removeEventListener('tap', laterCloseEvent); 48 | self.close(); 49 | }, 300)); 50 | }; 51 | this.scroller.addEventListener('doubletap', function() { 52 | if (laterClose) { 53 | laterClose.cancel(); 54 | laterClose = null; 55 | } 56 | }); 57 | this.element.addEventListener('webkitAnimationEnd', function() { 58 | if (self.element.classList.contains($.className('preview-out'))) { //close 59 | self.element.style.display = 'none'; 60 | self.element.classList.remove($.className('preview-out')); 61 | self.element.classList.remove($.className('preview-in')); 62 | laterClose = null; 63 | } else { //open 64 | self.loader.addEventListener('tap', laterCloseEvent); 65 | self.scroller.addEventListener('tap', laterCloseEvent); 66 | } 67 | }); 68 | this.element.addEventListener('slide', function(e) { 69 | if (self.options.zoom) { 70 | var lastZoomerEl = self.element.querySelector('.mui-zoom-wrapper:nth-child(' + (self.lastIndex + 1) + ')'); 71 | if (lastZoomerEl) { 72 | $(lastZoomerEl).zoom().setZoom(1); 73 | } 74 | } 75 | var slideNumber = e.detail.slideNumber; 76 | self.lastIndex = slideNumber; 77 | self.indicator && (self.indicator.innerText = (slideNumber + 1) + '/' + self.currentGroup.length); 78 | self._loadItem(slideNumber); 79 | 80 | }); 81 | }; 82 | proto.addImages = function(group, index) { 83 | this.groups = {}; 84 | var imgs = []; 85 | if (group) { 86 | if (group === defaultGroupName) { 87 | imgs = document.querySelectorAll("img[data-preview-src]:not([data-preview-group])"); 88 | } else { 89 | imgs = document.querySelectorAll("img[data-preview-src][data-preview-group='" + group + "']"); 90 | } 91 | } else { 92 | imgs = document.querySelectorAll("img[data-preview-src]"); 93 | } 94 | if (imgs.length) { 95 | for (var i = 0, len = imgs.length; i < len; i++) { 96 | this.addImage(imgs[i]); 97 | } 98 | } 99 | }; 100 | proto.addImage = function(img) { 101 | var group = img.getAttribute('data-preview-group'); 102 | group = group || defaultGroupName; 103 | if (!this.groups[group]) { 104 | this.groups[group] = []; 105 | } 106 | var src = img.getAttribute('src'); 107 | if (img.__mui_img_data && img.__mui_img_data.src === src) { //已缓存且图片未变化 108 | this.groups[group].push(img.__mui_img_data); 109 | } else { 110 | var lazyload = img.getAttribute('data-preview-src'); 111 | if (!lazyload) { 112 | lazyload = src; 113 | } 114 | var imgObj = { 115 | src: src, 116 | lazyload: src === lazyload ? '' : lazyload, 117 | loaded: src === lazyload ? true : false, 118 | sWidth: 0, 119 | sHeight: 0, 120 | sTop: 0, 121 | sLeft: 0, 122 | sScale: 1, 123 | el: img 124 | }; 125 | this.groups[group].push(imgObj); 126 | img.__mui_img_data = imgObj; 127 | } 128 | }; 129 | 130 | 131 | proto.empty = function() { 132 | this.scroller.innerHTML = ''; 133 | }; 134 | proto._initImgData = function(itemData, imgEl) { 135 | if (!itemData.sWidth) { 136 | var img = itemData.el; 137 | itemData.sWidth = img.offsetWidth; 138 | itemData.sHeight = img.offsetHeight; 139 | var offset = $.offset(img); 140 | itemData.sTop = offset.top; 141 | itemData.sLeft = offset.left; 142 | itemData.sScale = Math.max(itemData.sWidth / window.innerWidth, itemData.sHeight / window.innerHeight); 143 | } 144 | imgEl.style.webkitTransform = 'translate3d(0,0,0) scale(' + itemData.sScale + ')'; 145 | }; 146 | 147 | proto._getScale = function(from, to) { 148 | var scaleX = from.width / to.width; 149 | var scaleY = from.height / to.height; 150 | var scale = 1; 151 | if (scaleX <= scaleY) { 152 | scale = from.height / (to.height * scaleX); 153 | } else { 154 | scale = from.width / (to.width * scaleY); 155 | } 156 | return scale; 157 | }; 158 | proto._imgTransitionEnd = function(e) { 159 | var img = e.target; 160 | img.classList.remove($.className('transitioning')); 161 | img.removeEventListener('webkitTransitionEnd', this._imgTransitionEnd.bind(this)); 162 | }; 163 | proto._loadItem = function(index, isOpening) { //TODO 暂时仅支持img 164 | var itemEl = this.scroller.querySelector($.classSelector('.slider-item:nth-child(' + (index + 1) + ')')); 165 | var itemData = this.currentGroup[index]; 166 | var imgEl = itemEl.querySelector('img'); 167 | this._initImgData(itemData, imgEl); 168 | if (isOpening) { 169 | var posi = this._getPosition(itemData); 170 | imgEl.style.webkitTransitionDuration = '0ms'; 171 | imgEl.style.webkitTransform = 'translate3d(' + posi.x + 'px,' + posi.y + 'px,0) scale(' + itemData.sScale + ')'; 172 | imgEl.offsetHeight; 173 | } 174 | if (!itemData.loaded && imgEl.getAttribute('data-preview-lazyload')) { 175 | var self = this; 176 | self.loader.classList.add($.className('active')); 177 | //移动位置动画 178 | imgEl.style.webkitTransitionDuration = '0.5s'; 179 | imgEl.addEventListener('webkitTransitionEnd', self._imgTransitionEnd.bind(self)); 180 | imgEl.style.webkitTransform = 'translate3d(0,0,0) scale(' + itemData.sScale + ')'; 181 | this.loadImage(imgEl, function() { 182 | itemData.loaded = true; 183 | imgEl.src = itemData.lazyload; 184 | self._initZoom(itemEl, this.width, this.height); 185 | imgEl.classList.add($.className('transitioning')); 186 | imgEl.addEventListener('webkitTransitionEnd', self._imgTransitionEnd.bind(self)); 187 | imgEl.setAttribute('style', ''); 188 | imgEl.offsetHeight; 189 | self.loader.classList.remove($.className('active')); 190 | }); 191 | } else { 192 | itemData.lazyload && (imgEl.src = itemData.lazyload); 193 | this._initZoom(itemEl, imgEl.width, imgEl.height); 194 | imgEl.classList.add($.className('transitioning')); 195 | imgEl.addEventListener('webkitTransitionEnd', this._imgTransitionEnd.bind(this)); 196 | imgEl.setAttribute('style', ''); 197 | imgEl.offsetHeight; 198 | } 199 | this._preloadItem(index + 1); 200 | this._preloadItem(index - 1); 201 | }; 202 | proto._preloadItem = function(index) { 203 | var itemEl = this.scroller.querySelector($.classSelector('.slider-item:nth-child(' + (index + 1) + ')')); 204 | if (itemEl) { 205 | var itemData = this.currentGroup[index]; 206 | if (!itemData.sWidth) { 207 | var imgEl = itemEl.querySelector('img'); 208 | this._initImgData(itemData, imgEl); 209 | } 210 | } 211 | }; 212 | proto._initZoom = function(zoomWrapperEl, zoomerWidth, zoomerHeight) { 213 | if (!this.options.zoom) { 214 | return; 215 | } 216 | if (zoomWrapperEl.getAttribute('data-zoomer')) { 217 | return; 218 | } 219 | var zoomEl = zoomWrapperEl.querySelector($.classSelector('.zoom')); 220 | if (zoomEl.tagName === 'IMG') { 221 | var self = this; 222 | var maxZoom = self._getScale({ 223 | width: zoomWrapperEl.offsetWidth, 224 | height: zoomWrapperEl.offsetHeight 225 | }, { 226 | width: zoomerWidth, 227 | height: zoomerHeight 228 | }); 229 | $(zoomWrapperEl).zoom({ 230 | maxZoom: Math.max(maxZoom, 1) 231 | }); 232 | } else { 233 | $(zoomWrapperEl).zoom(); 234 | } 235 | }; 236 | proto.loadImage = function(imgEl, callback) { 237 | var onReady = function() { 238 | callback && callback.call(this); 239 | }; 240 | var img = new Image(); 241 | img.onload = onReady; 242 | img.onerror = onReady; 243 | img.src = imgEl.getAttribute('data-preview-lazyload'); 244 | }; 245 | proto.getRangeByIndex = function(index, length) { 246 | return { 247 | from: 0, 248 | to: length - 1 249 | }; 250 | // var from = Math.max(index - 1, 0); 251 | // var to = Math.min(index + 1, length); 252 | // if (index === length - 1) { 253 | // from = Math.max(length - 3, 0); 254 | // to = length - 1; 255 | // } 256 | // if (index === 0) { 257 | // from = 0; 258 | // to = Math.min(2, length - 1); 259 | // } 260 | // return { 261 | // from: from, 262 | // to: to 263 | // }; 264 | }; 265 | 266 | proto._getPosition = function(itemData) { 267 | var sLeft = itemData.sLeft - window.pageXOffset; 268 | var sTop = itemData.sTop - window.pageYOffset; 269 | var left = (window.innerWidth - itemData.sWidth) / 2; 270 | var top = (window.innerHeight - itemData.sHeight) / 2; 271 | return { 272 | left: sLeft, 273 | top: sTop, 274 | x: sLeft - left, 275 | y: sTop - top 276 | }; 277 | }; 278 | proto.refresh = function(index, groupArray) { 279 | this.currentGroup = groupArray; 280 | //重新生成slider 281 | var length = groupArray.length; 282 | var itemHtml = []; 283 | var currentRange = this.getRangeByIndex(index, length); 284 | var from = currentRange.from; 285 | var to = currentRange.to + 1; 286 | var currentIndex = index; 287 | var className = ''; 288 | var itemStr = ''; 289 | var wWidth = window.innerWidth; 290 | var wHeight = window.innerHeight; 291 | for (var i = 0; from < to; from++, i++) { 292 | var itemData = groupArray[from]; 293 | var style = ''; 294 | if (itemData.sWidth) { 295 | style = '-webkit-transform:translate3d(0,0,0) scale(' + itemData.sScale + ');transform:translate3d(0,0,0) scale(' + itemData.sScale + ')'; 296 | } 297 | itemStr = itemTemplate.replace('{{src}}', itemData.src).replace('{{lazyload}}', itemData.lazyload).replace('{{style}}', style); 298 | if (from === index) { 299 | currentIndex = i; 300 | className = $.className('active'); 301 | } else { 302 | className = ''; 303 | } 304 | itemHtml.push(itemStr.replace('{{className}}', className)); 305 | } 306 | this.scroller.innerHTML = itemHtml.join(''); 307 | this.element.style.display = 'block'; 308 | this.element.classList.add($.className('preview-in')); 309 | this.lastIndex = currentIndex; 310 | this.element.offsetHeight; 311 | $(this.element).slider().gotoItem(currentIndex, 0); 312 | this.indicator && (this.indicator.innerText = (currentIndex + 1) + '/' + this.currentGroup.length); 313 | this._loadItem(currentIndex, true); 314 | }; 315 | proto.openByGroup = function(index, group) { 316 | index = Math.min(Math.max(0, index), this.groups[group].length - 1); 317 | this.refresh(index, this.groups[group]); 318 | }; 319 | proto.open = function(index, group) { 320 | if (this.isShown()) { 321 | return; 322 | } 323 | if (typeof index === "number") { 324 | group = group || defaultGroupName; 325 | this.addImages(group, index); //刷新当前group 326 | this.openByGroup(index, group); 327 | } else { 328 | group = index.getAttribute('data-preview-group'); 329 | group = group || defaultGroupName; 330 | this.addImages(group, index); //刷新当前group 331 | this.openByGroup(this.groups[group].indexOf(index.__mui_img_data), group); 332 | } 333 | }; 334 | proto.close = function(index, group) { 335 | if (!this.isShown()) { 336 | return; 337 | } 338 | this.element.classList.remove($.className('preview-in')); 339 | this.element.classList.add($.className('preview-out')); 340 | var itemEl = this.scroller.querySelector($.classSelector('.slider-item:nth-child(' + (this.lastIndex + 1) + ')')); 341 | var imgEl = itemEl.querySelector('img'); 342 | if (imgEl) { 343 | imgEl.classList.add($.className('transitioning')); 344 | var itemData = this.currentGroup[this.lastIndex]; 345 | var posi = this._getPosition(itemData); 346 | var sLeft = posi.left; 347 | var sTop = posi.top; 348 | if (sTop > window.innerHeight || sLeft > window.innerWidth || sTop < 0 || sLeft < 0) { //out viewport 349 | imgEl.style.opacity = 0; 350 | imgEl.style.webkitTransitionDuration = '0.5s'; 351 | imgEl.style.webkitTransform = 'scale(' + itemData.sScale + ')'; 352 | } else { 353 | if (this.options.zoom) { 354 | $(imgEl.parentNode.parentNode).zoom().toggleZoom(0); 355 | } 356 | imgEl.style.webkitTransitionDuration = '0.5s'; 357 | imgEl.style.webkitTransform = 'translate3d(' + posi.x + 'px,' + posi.y + 'px,0) scale(' + itemData.sScale + ')'; 358 | } 359 | } 360 | var zoomers = this.element.querySelectorAll($.classSelector('.zoom-wrapper')); 361 | for (var i = 0, len = zoomers.length; i < len; i++) { 362 | $(zoomers[i]).zoom().destroy(); 363 | } 364 | $(this.element).slider().destroy(); 365 | // this.empty(); 366 | }; 367 | proto.isShown = function() { 368 | return this.element.classList.contains($.className('preview-in')); 369 | }; 370 | 371 | var previewImageApi = null; 372 | $.previewImage = function(options) { 373 | if (!previewImageApi) { 374 | previewImageApi = new PreviewImage(options); 375 | } 376 | return previewImageApi; 377 | }; 378 | $.getPreviewImage = function() { 379 | return previewImageApi; 380 | } 381 | 382 | })(mui, window); -------------------------------------------------------------------------------- /src/assets/js/mui.zoom.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var CLASS_ZOOM = $.className('zoom'); 3 | var CLASS_ZOOM_SCROLLER = $.className('zoom-scroller'); 4 | 5 | var SELECTOR_ZOOM = '.' + CLASS_ZOOM; 6 | var SELECTOR_ZOOM_SCROLLER = '.' + CLASS_ZOOM_SCROLLER; 7 | 8 | var EVENT_PINCH_START = 'pinchstart'; 9 | var EVENT_PINCH = 'pinch'; 10 | var EVENT_PINCH_END = 'pinchend'; 11 | if ('ongesturestart' in window) { 12 | EVENT_PINCH_START = 'gesturestart'; 13 | EVENT_PINCH = 'gesturechange'; 14 | EVENT_PINCH_END = 'gestureend'; 15 | } 16 | $.Zoom = function(element, options) { 17 | var zoom = this; 18 | 19 | zoom.options = $.extend($.Zoom.defaults, options); 20 | 21 | zoom.wrapper = zoom.element = element; 22 | zoom.scroller = element.querySelector(SELECTOR_ZOOM_SCROLLER); 23 | zoom.scrollerStyle = zoom.scroller && zoom.scroller.style; 24 | 25 | zoom.zoomer = element.querySelector(SELECTOR_ZOOM); 26 | zoom.zoomerStyle = zoom.zoomer && zoom.zoomer.style; 27 | 28 | zoom.init = function() { 29 | //自动启用 30 | $.options.gestureConfig.pinch = true; 31 | $.options.gestureConfig.doubletap = true; 32 | zoom.initEvents(); 33 | }; 34 | 35 | zoom.initEvents = function(detach) { 36 | var action = detach ? 'removeEventListener' : 'addEventListener'; 37 | var target = zoom.scroller; 38 | 39 | target[action](EVENT_PINCH_START, zoom.onPinchstart); 40 | target[action](EVENT_PINCH, zoom.onPinch); 41 | target[action](EVENT_PINCH_END, zoom.onPinchend); 42 | 43 | target[action]($.EVENT_START, zoom.onTouchstart); 44 | target[action]($.EVENT_MOVE, zoom.onTouchMove); 45 | target[action]($.EVENT_CANCEL, zoom.onTouchEnd); 46 | target[action]($.EVENT_END, zoom.onTouchEnd); 47 | 48 | target[action]('drag', zoom.dragEvent); 49 | target[action]('doubletap', zoom.doubleTapEvent); 50 | }; 51 | zoom.dragEvent = function(e) { 52 | if (imageIsMoved || isGesturing) { 53 | e.stopPropagation(); 54 | } 55 | }; 56 | zoom.doubleTapEvent = function(e) { 57 | zoom.toggleZoom(e.detail.center); 58 | }; 59 | zoom.transition = function(style, time) { 60 | time = time || 0; 61 | style['webkitTransitionDuration'] = time + 'ms'; 62 | return zoom; 63 | }; 64 | zoom.translate = function(style, x, y) { 65 | x = x || 0; 66 | y = y || 0; 67 | style['webkitTransform'] = 'translate3d(' + x + 'px,' + y + 'px,0px)'; 68 | return zoom; 69 | }; 70 | zoom.scale = function(style, scale) { 71 | scale = scale || 1; 72 | style['webkitTransform'] = 'translate3d(0,0,0) scale(' + scale + ')'; 73 | return zoom; 74 | }; 75 | zoom.scrollerTransition = function(time) { 76 | return zoom.transition(zoom.scrollerStyle, time); 77 | }; 78 | zoom.scrollerTransform = function(x, y) { 79 | return zoom.translate(zoom.scrollerStyle, x, y); 80 | }; 81 | zoom.zoomerTransition = function(time) { 82 | return zoom.transition(zoom.zoomerStyle, time); 83 | }; 84 | zoom.zoomerTransform = function(scale) { 85 | return zoom.scale(zoom.zoomerStyle, scale); 86 | }; 87 | 88 | // Gestures 89 | var scale = 1, 90 | currentScale = 1, 91 | isScaling = false, 92 | isGesturing = false; 93 | zoom.onPinchstart = function(e) { 94 | isGesturing = true; 95 | }; 96 | zoom.onPinch = function(e) { 97 | if (!isScaling) { 98 | zoom.zoomerTransition(0); 99 | isScaling = true; 100 | } 101 | scale = (e.detail ? e.detail.scale : e.scale) * currentScale; 102 | if (scale > zoom.options.maxZoom) { 103 | scale = zoom.options.maxZoom - 1 + Math.pow((scale - zoom.options.maxZoom + 1), 0.5); 104 | } 105 | if (scale < zoom.options.minZoom) { 106 | scale = zoom.options.minZoom + 1 - Math.pow((zoom.options.minZoom - scale + 1), 0.5); 107 | } 108 | zoom.zoomerTransform(scale); 109 | }; 110 | zoom.onPinchend = function(e) { 111 | scale = Math.max(Math.min(scale, zoom.options.maxZoom), zoom.options.minZoom); 112 | zoom.zoomerTransition(zoom.options.speed).zoomerTransform(scale); 113 | currentScale = scale; 114 | isScaling = false; 115 | }; 116 | zoom.setZoom = function(newScale) { 117 | scale = currentScale = newScale; 118 | zoom.scrollerTransition(zoom.options.speed).scrollerTransform(0, 0); 119 | zoom.zoomerTransition(zoom.options.speed).zoomerTransform(scale); 120 | }; 121 | zoom.toggleZoom = function(position, speed) { 122 | if (typeof position === 'number') { 123 | speed = position; 124 | position = undefined; 125 | } 126 | speed = typeof speed === 'undefined' ? zoom.options.speed : speed; 127 | if (scale && scale !== 1) { 128 | scale = currentScale = 1; 129 | zoom.scrollerTransition(speed).scrollerTransform(0, 0); 130 | } else { 131 | scale = currentScale = zoom.options.maxZoom; 132 | if (position) { 133 | var offset = $.offset(zoom.zoomer); 134 | var top = offset.top; 135 | var left = offset.left; 136 | var offsetX = (position.x - left) * scale; 137 | var offsetY = (position.y - top) * scale; 138 | this._cal(); 139 | if (offsetX >= imageMaxX && offsetX <= (imageMaxX + wrapperWidth)) { //center 140 | offsetX = imageMaxX - offsetX + wrapperWidth / 2; 141 | } else if (offsetX < imageMaxX) { //left 142 | offsetX = imageMaxX - offsetX + wrapperWidth / 2; 143 | } else if (offsetX > (imageMaxX + wrapperWidth)) { //right 144 | offsetX = imageMaxX + wrapperWidth - offsetX - wrapperWidth / 2; 145 | } 146 | if (offsetY >= imageMaxY && offsetY <= (imageMaxY + wrapperHeight)) { //middle 147 | offsetY = imageMaxY - offsetY + wrapperHeight / 2; 148 | } else if (offsetY < imageMaxY) { //top 149 | offsetY = imageMaxY - offsetY + wrapperHeight / 2; 150 | } else if (offsetY > (imageMaxY + wrapperHeight)) { //bottom 151 | offsetY = imageMaxY + wrapperHeight - offsetY - wrapperHeight / 2; 152 | } 153 | offsetX = Math.min(Math.max(offsetX, imageMinX), imageMaxX); 154 | offsetY = Math.min(Math.max(offsetY, imageMinY), imageMaxY); 155 | zoom.scrollerTransition(speed).scrollerTransform(offsetX, offsetY); 156 | } else { 157 | zoom.scrollerTransition(speed).scrollerTransform(0, 0); 158 | } 159 | } 160 | zoom.zoomerTransition(speed).zoomerTransform(scale); 161 | }; 162 | 163 | zoom._cal = function() { 164 | wrapperWidth = zoom.wrapper.offsetWidth; 165 | wrapperHeight = zoom.wrapper.offsetHeight; 166 | imageWidth = zoom.zoomer.offsetWidth; 167 | imageHeight = zoom.zoomer.offsetHeight; 168 | var scaledWidth = imageWidth * scale; 169 | var scaledHeight = imageHeight * scale; 170 | imageMinX = Math.min((wrapperWidth / 2 - scaledWidth / 2), 0); 171 | imageMaxX = -imageMinX; 172 | imageMinY = Math.min((wrapperHeight / 2 - scaledHeight / 2), 0); 173 | imageMaxY = -imageMinY; 174 | }; 175 | 176 | var wrapperWidth, wrapperHeight, imageIsTouched, imageIsMoved, imageCurrentX, imageCurrentY, imageMinX, imageMinY, imageMaxX, imageMaxY, imageWidth, imageHeight, imageTouchesStart = {}, 177 | imageTouchesCurrent = {}, 178 | imageStartX, imageStartY, velocityPrevPositionX, velocityPrevTime, velocityX, velocityPrevPositionY, velocityY; 179 | 180 | zoom.onTouchstart = function(e) { 181 | e.preventDefault(); 182 | imageIsTouched = true; 183 | imageTouchesStart.x = e.type === $.EVENT_START ? e.targetTouches[0].pageX : e.pageX; 184 | imageTouchesStart.y = e.type === $.EVENT_START ? e.targetTouches[0].pageY : e.pageY; 185 | }; 186 | zoom.onTouchMove = function(e) { 187 | e.preventDefault(); 188 | if (!imageIsTouched) return; 189 | if (!imageIsMoved) { 190 | wrapperWidth = zoom.wrapper.offsetWidth; 191 | wrapperHeight = zoom.wrapper.offsetHeight; 192 | imageWidth = zoom.zoomer.offsetWidth; 193 | imageHeight = zoom.zoomer.offsetHeight; 194 | var translate = $.parseTranslateMatrix($.getStyles(zoom.scroller, 'webkitTransform')); 195 | imageStartX = translate.x || 0; 196 | imageStartY = translate.y || 0; 197 | zoom.scrollerTransition(0); 198 | } 199 | var scaledWidth = imageWidth * scale; 200 | var scaledHeight = imageHeight * scale; 201 | 202 | if (scaledWidth < wrapperWidth && scaledHeight < wrapperHeight) return; 203 | 204 | imageMinX = Math.min((wrapperWidth / 2 - scaledWidth / 2), 0); 205 | imageMaxX = -imageMinX; 206 | imageMinY = Math.min((wrapperHeight / 2 - scaledHeight / 2), 0); 207 | imageMaxY = -imageMinY; 208 | 209 | imageTouchesCurrent.x = e.type === $.EVENT_MOVE ? e.targetTouches[0].pageX : e.pageX; 210 | imageTouchesCurrent.y = e.type === $.EVENT_MOVE ? e.targetTouches[0].pageY : e.pageY; 211 | 212 | if (!imageIsMoved && !isScaling) { 213 | // if (Math.abs(imageTouchesCurrent.y - imageTouchesStart.y) < Math.abs(imageTouchesCurrent.x - imageTouchesStart.x)) { 214 | //TODO 此处需要优化,当遇到长图,需要上下滚动时,下列判断会导致滚动不流畅 215 | if ( 216 | (Math.floor(imageMinX) === Math.floor(imageStartX) && imageTouchesCurrent.x < imageTouchesStart.x) || 217 | (Math.floor(imageMaxX) === Math.floor(imageStartX) && imageTouchesCurrent.x > imageTouchesStart.x) 218 | ) { 219 | imageIsTouched = false; 220 | return; 221 | } 222 | // } 223 | } 224 | imageIsMoved = true; 225 | imageCurrentX = imageTouchesCurrent.x - imageTouchesStart.x + imageStartX; 226 | imageCurrentY = imageTouchesCurrent.y - imageTouchesStart.y + imageStartY; 227 | 228 | if (imageCurrentX < imageMinX) { 229 | imageCurrentX = imageMinX + 1 - Math.pow((imageMinX - imageCurrentX + 1), 0.8); 230 | } 231 | if (imageCurrentX > imageMaxX) { 232 | imageCurrentX = imageMaxX - 1 + Math.pow((imageCurrentX - imageMaxX + 1), 0.8); 233 | } 234 | 235 | if (imageCurrentY < imageMinY) { 236 | imageCurrentY = imageMinY + 1 - Math.pow((imageMinY - imageCurrentY + 1), 0.8); 237 | } 238 | if (imageCurrentY > imageMaxY) { 239 | imageCurrentY = imageMaxY - 1 + Math.pow((imageCurrentY - imageMaxY + 1), 0.8); 240 | } 241 | 242 | //Velocity 243 | if (!velocityPrevPositionX) velocityPrevPositionX = imageTouchesCurrent.x; 244 | if (!velocityPrevPositionY) velocityPrevPositionY = imageTouchesCurrent.y; 245 | if (!velocityPrevTime) velocityPrevTime = $.now(); 246 | velocityX = (imageTouchesCurrent.x - velocityPrevPositionX) / ($.now() - velocityPrevTime) / 2; 247 | velocityY = (imageTouchesCurrent.y - velocityPrevPositionY) / ($.now() - velocityPrevTime) / 2; 248 | if (Math.abs(imageTouchesCurrent.x - velocityPrevPositionX) < 2) velocityX = 0; 249 | if (Math.abs(imageTouchesCurrent.y - velocityPrevPositionY) < 2) velocityY = 0; 250 | velocityPrevPositionX = imageTouchesCurrent.x; 251 | velocityPrevPositionY = imageTouchesCurrent.y; 252 | velocityPrevTime = $.now(); 253 | 254 | zoom.scrollerTransform(imageCurrentX, imageCurrentY); 255 | }; 256 | zoom.onTouchEnd = function(e) { 257 | if (!e.touches.length) { 258 | isGesturing = false; 259 | } 260 | if (!imageIsTouched || !imageIsMoved) { 261 | imageIsTouched = false; 262 | imageIsMoved = false; 263 | return; 264 | } 265 | imageIsTouched = false; 266 | imageIsMoved = false; 267 | var momentumDurationX = 300; 268 | var momentumDurationY = 300; 269 | var momentumDistanceX = velocityX * momentumDurationX; 270 | var newPositionX = imageCurrentX + momentumDistanceX; 271 | var momentumDistanceY = velocityY * momentumDurationY; 272 | var newPositionY = imageCurrentY + momentumDistanceY; 273 | 274 | if (velocityX !== 0) momentumDurationX = Math.abs((newPositionX - imageCurrentX) / velocityX); 275 | if (velocityY !== 0) momentumDurationY = Math.abs((newPositionY - imageCurrentY) / velocityY); 276 | var momentumDuration = Math.max(momentumDurationX, momentumDurationY); 277 | 278 | imageCurrentX = newPositionX; 279 | imageCurrentY = newPositionY; 280 | 281 | var scaledWidth = imageWidth * scale; 282 | var scaledHeight = imageHeight * scale; 283 | imageMinX = Math.min((wrapperWidth / 2 - scaledWidth / 2), 0); 284 | imageMaxX = -imageMinX; 285 | imageMinY = Math.min((wrapperHeight / 2 - scaledHeight / 2), 0); 286 | imageMaxY = -imageMinY; 287 | imageCurrentX = Math.max(Math.min(imageCurrentX, imageMaxX), imageMinX); 288 | imageCurrentY = Math.max(Math.min(imageCurrentY, imageMaxY), imageMinY); 289 | 290 | zoom.scrollerTransition(momentumDuration).scrollerTransform(imageCurrentX, imageCurrentY); 291 | }; 292 | zoom.destroy = function() { 293 | zoom.initEvents(true); //detach 294 | delete $.data[zoom.wrapper.getAttribute('data-zoomer')]; 295 | zoom.wrapper.setAttribute('data-zoomer', ''); 296 | } 297 | zoom.init(); 298 | return zoom; 299 | }; 300 | $.Zoom.defaults = { 301 | speed: 300, 302 | maxZoom: 3, 303 | minZoom: 1, 304 | }; 305 | $.fn.zoom = function(options) { 306 | var zoomApis = []; 307 | this.each(function() { 308 | var zoomApi = null; 309 | var self = this; 310 | var id = self.getAttribute('data-zoomer'); 311 | if (!id) { 312 | id = ++$.uuid; 313 | $.data[id] = zoomApi = new $.Zoom(self, options); 314 | self.setAttribute('data-zoomer', id); 315 | } else { 316 | zoomApi = $.data[id]; 317 | } 318 | zoomApis.push(zoomApi); 319 | }); 320 | return zoomApis.length === 1 ? zoomApis[0] : zoomApis; 321 | }; 322 | })(mui, window); -------------------------------------------------------------------------------- /src/components/component-demo/component-demo.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

我是自定义组件

4 | {{text}} 5 |

父亲向儿子传递的数据:{{fatherToSonData}}

6 | 7 |
8 |

自定义组件END

9 |
10 | -------------------------------------------------------------------------------- /src/components/component-demo/component-demo.scss: -------------------------------------------------------------------------------- 1 | component-demo { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/components/component-demo/component-demo.ts: -------------------------------------------------------------------------------- 1 | import { Component ,Input ,Output ,EventEmitter } from '@angular/core'; 2 | 3 | /** 4 | * 自定义组件demo 5 | * 6 | * 1. 父亲向儿子传递数据 7 | * @Input() 8 | * 9 | * 2. 儿子向父亲传递事件 10 | * @Output() 11 | */ 12 | @Component({ 13 | selector: 'component-demo', 14 | templateUrl: 'component-demo.html' 15 | }) 16 | export class ComponentDemoComponent { 17 | 18 | //这个案例中,父组件向儿子传递了一个数据,这个数据被绑定到儿子的 fatherToSonData 属性中 19 | @Input('fatherToSonData') fatherToSonData :string; 20 | 21 | //向外传递的事件 22 | @Output() parentClick = new EventEmitter(); 23 | 24 | //儿子独立作用域中的属性 25 | text: string; 26 | 27 | constructor() { 28 | // console.log('Hello ComponentDemoComponent Component'); 29 | this.text = 'Hello World'; 30 | } 31 | 32 | //儿子的点击事件 33 | sonClick(){ 34 | console.log('son click'); 35 | this.parentClick.emit( 36 | { 37 | sonToFaterData: '我是子元素传递回去事件的参数', 38 | }) 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/components/components.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {PreviewimgComponent} from './previewimg/previewimg'; 3 | import {ComponentDemoComponent} from './component-demo/component-demo'; 4 | import {MapPositionPickerComponent} from './map-position-picker/map-position-picker'; 5 | 6 | @NgModule({ 7 | declarations: [PreviewimgComponent, 8 | ComponentDemoComponent, 9 | MapPositionPickerComponent], 10 | imports: [], 11 | exports: [PreviewimgComponent, 12 | ComponentDemoComponent, 13 | MapPositionPickerComponent] 14 | }) 15 | export class ComponentsModule { 16 | } 17 | -------------------------------------------------------------------------------- /src/components/map-position-picker/map-position-picker.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | -------------------------------------------------------------------------------- /src/components/map-position-picker/map-position-picker.scss: -------------------------------------------------------------------------------- 1 | map-position-picker { 2 | .main{ 3 | height: 60%; 4 | width: 100%; 5 | margin: 0; 6 | padding: 0; 7 | } 8 | .map { 9 | height: 100%; 10 | width: 100%; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/components/map-position-picker/map-position-picker.ts: -------------------------------------------------------------------------------- 1 | import {Component, EventEmitter, Output} from '@angular/core'; 2 | 3 | declare var AMap: any; 4 | declare var AMapUI: any; 5 | 6 | import {MapPositionModel} from '../../model/mapPositionModel'; 7 | 8 | /*** 9 | * 高德地图 - 地图选点反推地址组件 10 | * 1. 组件依赖高德官方两个js,在入口文件index.html引入 11 | * 12 | * 13 | * 14 | * 15 | */ 16 | 17 | @Component({ 18 | selector: 'map-position-picker', 19 | templateUrl: 'map-position-picker.html' 20 | }) 21 | export class MapPositionPickerComponent { 22 | @Output() outputPosition: EventEmitter = new EventEmitter(); 23 | loaded: boolean = false; 24 | //所选点 25 | position: MapPositionModel; 26 | //替补点 27 | alternate: Array = []; 28 | 29 | constructor() { 30 | console.log('Hello MapPositionPickerComponent Component'); 31 | //初始化地图 32 | this.initMap(); 33 | } 34 | 35 | //初始化地图 36 | initMap() { 37 | AMapUI.loadUI(['misc/PositionPicker'], (PositionPicker) => { 38 | // 1.制作地图 39 | var map = new AMap.Map('container', { 40 | zoom: 13, 41 | // 地图是否可通过鼠标滚轮缩放浏览,默认为true 42 | scrollWheel: false, 43 | // center:[], 44 | }) 45 | 46 | // 2.定位当前位置,并添加标记到当前地图,把位置作为地图中心点 47 | map.plugin('AMap.Geolocation', () => { 48 | let geolocation = new AMap.Geolocation({ 49 | enableHighAccuracy: true,//是否使用高精度定位,默认:true 50 | timeout: 10000, //超过10秒后停止定位,默认:无穷大 51 | maximumAge: 0, //定位结果缓存0毫秒,默认:0 52 | convert: true, //自动偏移坐标,偏移后的坐标为高德坐标,默认:true 53 | showButton: true, //显示定位按钮,默认:true 54 | buttonPosition: 'LB', //定位按钮停靠位置,默认:'LB',左下角 55 | buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20) 56 | showMarker: true, //定位成功后在定位到的位置显示点标记,默认:true 57 | showCircle: true, //定位成功后用圆圈表示定位精度范围,默认:true 58 | panToLocation: true, //定位成功后将定位到的位置作为地图中心点,默认:true 59 | zoomToAccuracy: false //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false 60 | }); 61 | map.addControl(geolocation); 62 | geolocation.getCurrentPosition(); 63 | //定位成功 64 | AMap.event.addListener(geolocation, 'complete', (data) => { 65 | }); 66 | //定位失败 67 | AMap.event.addListener(geolocation, 'error', (err) => { 68 | console.log(err) 69 | }); 70 | }); 71 | 72 | 73 | // 3.地图拖动选址 74 | var positionPicker = new PositionPicker({ 75 | mode: 'dragMap', 76 | map: map 77 | }); 78 | positionPicker.on('success', (positionResult) => { 79 | // console.log(positionResult); 80 | 81 | this.position = { 82 | address: positionResult.address, 83 | location: positionResult.position, 84 | }; 85 | this.alternate =positionResult.regeocode.pois; 86 | this.loaded = true; 87 | //向父元素传播事件 88 | this.outputPosition.emit({ 89 | firstPosition:this.position, 90 | morePostion:this.alternate, 91 | }); 92 | }); 93 | positionPicker.on('fail', (positionResult) => { 94 | console.log('定位失败'); 95 | }); 96 | //开始选点 97 | positionPicker.start(); 98 | map.panBy(0, 1); 99 | positionPicker.setMode('dragMap'); 100 | 101 | map.addControl(new AMap.ToolBar({ 102 | liteStyle: true 103 | })) 104 | }); 105 | } 106 | 107 | //地图定位 108 | mapGeolocation(successCallback) { 109 | 110 | } 111 | 112 | //地图定位成功回调 113 | mapGeolocationSuccessCallback(data) { 114 | console.log('定位当前位置成功'); 115 | console.log('经度:' + data.position.getLng()); 116 | console.log('纬度:' + data.position.getLat()); 117 | if (data.accuracy) { 118 | console.log('精度:' + data.accuracy + ' 米'); 119 | } 120 | //如为IP精确定位结果则没有精度信息 121 | console.log('是否经过偏移:' + (data.isConverted ? '是' : '否')); 122 | } 123 | 124 | //地图定位出错回调 125 | mapGeolocationErrorCallback(error) { 126 | console.log('定位失败', error); 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/components/previewimg/previewimg.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | {{text}} 4 |
5 | -------------------------------------------------------------------------------- /src/components/previewimg/previewimg.scss: -------------------------------------------------------------------------------- 1 | previewimg { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/components/previewimg/previewimg.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | /** 4 | * Generated class for the PreviewimgComponent component. 5 | * 6 | * See https://angular.io/api/core/Component for more info on Angular 7 | * Components. 8 | */ 9 | @Component({ 10 | selector: 'previewimg', 11 | templateUrl: 'previewimg.html' 12 | }) 13 | export class PreviewimgComponent { 14 | 15 | text: string; 16 | 17 | constructor() { 18 | console.log('Hello PreviewimgComponent Component'); 19 | this.text = 'Hello World'; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Ionic App 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ionic", 3 | "short_name": "Ionic", 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/model/mapPositionModel.ts: -------------------------------------------------------------------------------- 1 | export class MapPositionModel{ 2 | address:any; 3 | location:object; 4 | } 5 | -------------------------------------------------------------------------------- /src/model/share.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by 谢大见 on 2017/6/30. 3 | */ 4 | export class ShareModel { // 分享 5 | title: string; // 标题 6 | banner: string; // 标语提示 7 | descr: string; // 描述 8 | thumb: string; // 显示的缩略图 9 | url: string; // 链接 10 | } -------------------------------------------------------------------------------- /src/pages/baidu-map/baidu-map.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 百度地图 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /src/pages/baidu-map/baidu-map.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { IonicPageModule } from 'ionic-angular'; 3 | import { BaiduMapPage } from './baidu-map'; 4 | 5 | @NgModule({ 6 | declarations: [ 7 | BaiduMapPage, 8 | ], 9 | imports: [ 10 | IonicPageModule.forChild(BaiduMapPage), 11 | ], 12 | }) 13 | export class BaiduMapPageModule {} 14 | -------------------------------------------------------------------------------- /src/pages/baidu-map/baidu-map.scss: -------------------------------------------------------------------------------- 1 | page-baidu-map { 2 | #map_container{ 3 | width: 100%; 4 | height: 80%; 5 | } 6 | #btn-location{ 7 | position: relative; 8 | top: 10px; 9 | left: 0; 10 | z-index: 999; 11 | } 12 | .btn_loaction{ 13 | padding-right:10px; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/pages/baidu-map/baidu-map.ts: -------------------------------------------------------------------------------- 1 | import { Component,ViewChild, ElementRef } from '@angular/core'; 2 | import { IonicPage, NavController, NavParams } from 'ionic-angular'; 3 | 4 | //引入html5定位 5 | import {GeolocationProvider} from '../../providers/geolocation/geolocation'; 6 | 7 | // baidu map 8 | declare var BMap; 9 | declare var BMap_Symbol_SHAPE_POINT; 10 | 11 | @IonicPage() 12 | @Component({ 13 | selector: 'page-baidu-map', 14 | templateUrl: 'baidu-map.html', 15 | }) 16 | export class BaiduMapPage { 17 | 18 | @ViewChild('map') map_container: ElementRef; 19 | map: any;//地图对象 20 | marker: any;//标记 21 | geolocation1: any; 22 | myIcon: any; 23 | 24 | constructor(public navCtrl: NavController, 25 | public html5Geolocation: GeolocationProvider, 26 | public navParams: NavParams) { 27 | this.html5Geolocation.watchPosition(); 28 | this.myIcon = new BMap.Icon("assets/icon/favicon.ico", new BMap.Size(30, 30)); 29 | } 30 | 31 | ionViewDidLoad() { 32 | console.log('ionViewDidLoad BaiduMapPage'); 33 | } 34 | ionViewDidEnter() { 35 | let map = 36 | this.map = 37 | new BMap.Map( 38 | this.map_container.nativeElement, 39 | { 40 | enableMapClick: true,//点击拖拽 41 | enableScrollWheelZoom: true,//启动滚轮放大缩小,默认禁用 42 | enableContinuousZoom: true //连续缩放效果,默认禁用 43 | } 44 | );//创建地图实例 45 | 46 | // map.centerAndZoom("广州",17); //设置城市设置中心和地图显示级别 47 | // map.addControl(new BMap.MapTypeControl());//地图类型切换 48 | // map.setCurrentCity("广州"); //设置当前城市 49 | 50 | let point = new BMap.Point(113.38028471135, 23.129702256122);//坐标可以通过百度地图坐标拾取器获取 51 | let marker = new BMap.Marker(point); 52 | this.map.addOverlay(marker); 53 | map.centerAndZoom(point, 18);//设置中心和地图显示级别 54 | 55 | // let sizeMap = new BMap.Size(10, 80);//显示位置 56 | // map.addControl(new BMap.NavigationControl()); 57 | 58 | // let myIcon = new BMap.Icon("assets/icon/favicon.ico", new BMap.Size(300, 157)); 59 | // let marker = this.marker = new BMap.Marker(point, { icon: myIcon }); 60 | // map.addOverlay(marker); 61 | } 62 | 63 | //浏览器定位 64 | getLocationByBrowser() { 65 | let geolocation1 = this.geolocation1 = new BMap.Geolocation(); 66 | geolocation1.getCurrentPosition((r) => { 67 | let mk = this.marker = new BMap.Marker(r.point, { icon: this.myIcon }); 68 | console.log('打印:',geolocation1.getStatus()); 69 | if (geolocation1.getStatus() == 'BMAP_STATUS_SUCCESS') { 70 | this.map.addOverlay(mk); 71 | this.map.panTo(r.point, 16); 72 | console.log('浏览器定位:您的位置是 ' + r.point.lng + ',' + r.point.lat); 73 | } 74 | else { 75 | alert('failed' + this.geolocation1.getStatus()); 76 | } 77 | }, { enableHighAccuracy: false }) 78 | } 79 | 80 | //IP定位 81 | getLocationByIp() { 82 | let myCity = new BMap.LocalCity(); 83 | myCity.get(result => { 84 | let cityName = result.name; 85 | this.map.setCenter(cityName); 86 | console.log("当前定位城市:" + cityName); 87 | }); 88 | } 89 | 90 | //城市定位 91 | getLocationByCity() { 92 | let city = "郑州"; 93 | if (city != "") { 94 | this.map.centerAndZoom(city, 16); // 用城市名设置地图中心点 95 | } 96 | } 97 | 98 | //经纬度定位 99 | getLocationByLatLon() { 100 | let aa=this.html5Geolocation.latitude; 101 | let bb=this.html5Geolocation.longitude; 102 | let point = new BMap.Point(bb, aa); 103 | let marker = this.marker = new BMap.Marker(point, { icon: this.myIcon }); 104 | this.map.addOverlay(marker); 105 | this.map.centerAndZoom(point, 16); 106 | } 107 | 108 | //GPS点击定位 109 | getLocation() { 110 | // this.geolocation.getCurrentPosition().then((resp) => { 111 | // let locationPoint = new BMap.Point(resp.coords.longitude, resp.coords.latitude); 112 | // let convertor = new BMap.Convertor(); 113 | // let pointArr = []; 114 | // pointArr.push(locationPoint); 115 | // convertor.translate(pointArr, 1, 5, (data) => { 116 | // if (data.status === 0) { 117 | // let marker = this.marker = new BMap.Marker(data.points[0], { icon: this.myIcon }); 118 | // this.map.panTo(data.points[0]); 119 | // marker.setPosition(data.points[0]); 120 | // this.map.addOverlay(marker); 121 | // } 122 | // }) 123 | // console.log('GPS定位:您的位置是 ' + resp.coords.longitude + ',' + resp.coords.latitude); 124 | // }) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/pages/browser/browser-popover.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { IonicPageModule } from 'ionic-angular'; 3 | import { BrowserPopoverPage } from './browser-popover'; 4 | 5 | @NgModule({ 6 | declarations: [ 7 | BrowserPopoverPage, 8 | ], 9 | imports: [ 10 | IonicPageModule.forChild(BrowserPopoverPage), 11 | ], 12 | }) 13 | export class BrowserPopoverPageModule {} 14 | -------------------------------------------------------------------------------- /src/pages/browser/browser-popover.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { IonicPage, NavController, NavParams ,ViewController} from 'ionic-angular'; 3 | 4 | /** 5 | * Generated class for the BrowserPopoverPage page. 6 | * 7 | * See https://ionicframework.com/docs/components/#navigation for more info on 8 | * Ionic pages and navigation. 9 | */ 10 | 11 | @IonicPage() 12 | @Component({ 13 | template: ` 14 | 15 | 16 | 17 | 18 | 19 | ` 20 | }) 21 | export class BrowserPopoverPage { 22 | parentCallback: {refresh: () => void, share?: () => void, close: () => void}; 23 | 24 | constructor(public viewCtrl: ViewController, 25 | private navParams: NavParams) { 26 | this.parentCallback = this.navParams.data.callback; 27 | } 28 | 29 | // 刷新 30 | refresh() { 31 | this.parentCallback.refresh(); 32 | this.viewCtrl.dismiss(); 33 | } 34 | 35 | // 分享 36 | share() { 37 | this.parentCallback.share(); 38 | this.viewCtrl.dismiss(); 39 | } 40 | 41 | close() { 42 | this.viewCtrl.dismiss(); 43 | this.parentCallback.close(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/pages/browser/browser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{browser.title}} 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 | 20 | 25 |
26 | 27 | -------------------------------------------------------------------------------- /src/pages/browser/browser.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { IonicPageModule } from 'ionic-angular'; 3 | import { BrowserPage } from './browser'; 4 | 5 | 6 | @NgModule({ 7 | declarations: [ 8 | BrowserPage, 9 | ], 10 | imports: [ 11 | IonicPageModule.forChild(BrowserPage), 12 | ], 13 | }) 14 | export class BrowserPageModule {} 15 | -------------------------------------------------------------------------------- /src/pages/browser/browser.scss: -------------------------------------------------------------------------------- 1 | page-browser { 2 | $progress-height: 0.2rem; 3 | //$progress-bg: #d43f3a; 4 | //$progress-bg: linear-gradient(-45deg, #333 100%, #324512 60%,rgba(255,255,255,0.5) 0%); 5 | //$progress-bg: linear-gradient(left, #5bd8ff, #ff0000); 6 | //$progress-bg: linear-gradient(-45deg, rgba(255,255,255,0.5)0%, #324512 60%,#333 100%); 7 | $progress-bg: #77b6ff; 8 | 9 | /*.scroll-content { 10 | overflow: hidden; 11 | }*/ 12 | 13 | .content { 14 | height: 100%; 15 | } 16 | 17 | .progress{ 18 | position: absolute; 19 | top: 0; 20 | right: 0; 21 | left: 0; 22 | height: $progress-height; 23 | background: #f5f5f5; 24 | z-index: 200; 25 | 26 | .progress-inner{ 27 | width: 0; 28 | background: $progress-bg; 29 | position: absolute; 30 | top: 0; 31 | left: 0; 32 | bottom: 0; 33 | 34 | box-shadow: 0 0 10px rgba(119,182,255,0.7); 35 | -webkit-transition: width 0.4s ease; 36 | transition: width 0.4s ease; 37 | } 38 | } 39 | 40 | .iframe { 41 | width: 100%; 42 | height: 100%; 43 | position: absolute; 44 | overflow: auto; 45 | border: none; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/pages/browser/browser.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { IonicPage, NavController, NavParams ,PopoverController} from 'ionic-angular'; 3 | import { DomSanitizer } from "@angular/platform-browser"; 4 | import { BrowserPopoverPage } from "./browser-popover"; 5 | 6 | /** 7 | * Generated class for the BrowserPage page. 8 | * 9 | * See https://ionicframework.com/docs/components/#navigation for more info on 10 | * Ionic pages and navigation. 11 | */ 12 | 13 | @IonicPage() 14 | @Component({ 15 | selector: 'page-browser', 16 | templateUrl: 'browser.html', 17 | }) 18 | export class BrowserPage { 19 | browser: any = { 20 | isLoaded: false, // 网页是否被加载 21 | proObj: null, // 进度条对象 22 | progress: 0, // 网页访问的进度条 23 | secUrl: '', // 安全链接 24 | 25 | title: '加载中', 26 | url: '', 27 | share: null // 是否具有分享功能(传递一个分享对象ShareModel过来) 28 | }; 29 | 30 | shareConfig: any = { 31 | isShow: true 32 | }; // 分享控制的配置 33 | 34 | constructor(public navCtrl: NavController, 35 | private params: NavParams, 36 | private sanitizer: DomSanitizer, 37 | private popoverCtrl: PopoverController) { 38 | let browser = this.params.get('browser'); 39 | if(browser) { 40 | this.browser.title = browser.title; 41 | this.browser.url = browser.url; 42 | // Angular 2 在编译的时候,会自动清理 HTML 输入并转义不安全的代码,因此在这种情况下,脚本不会运行,只能在屏幕上显示为文本。 43 | // iframe 的 src 属性是资源 URL 安全上下文,因为不可信源可以在用户不知情的情况下执行某些不安全的操作。但如果我们确认资源的 URL 是安全的,可以使用 Angular 2 中提供的 DomSanitizer 服告知 Angular 该 URL 地址是安全的 44 | this.browser.secUrl = this.sanitizer.bypassSecurityTrustResourceUrl(browser.url); 45 | 46 | if(browser.share) { 47 | this.browser.share = browser.share; 48 | } 49 | 50 | } else { 51 | this.browser.secUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.browser.url); 52 | } 53 | this.reload(); 54 | } 55 | 56 | ionViewDidLoad() { 57 | if(!this.browser.proObj) { 58 | this.browser.proObj = document.getElementById('progress'); 59 | } 60 | this.onprogress(); 61 | } 62 | 63 | // 生成随机数 64 | private random(min: number, max: number): number { 65 | return Math.floor(Math.random() * (max - min + 1) + min); 66 | } 67 | 68 | // 网页访问进度 69 | private onprogress() { 70 | // 随机时间 71 | let timeout = this.random(10, 30); 72 | 73 | let timer = setTimeout(() => { 74 | if(this.browser.isLoaded) { 75 | this.browser.proObj.style.width = '100%'; 76 | clearTimeout(timer); 77 | return; 78 | } 79 | 80 | // 随机进度 81 | this.browser.progress += this.random(1, 5); 82 | 83 | // 随机进度不能超过 90%,以免页面还没加载完毕,进度已经 100% 了 84 | if(this.browser.progress > 90){ 85 | this.browser.progress = 90; 86 | } 87 | 88 | this.browser.proObj.style.width = this.browser.progress + '%'; 89 | this.onprogress(); 90 | }, timeout); 91 | } 92 | 93 | // 如果iframe页面加载成功后 94 | loaded() { 95 | this.browser.isLoaded = true; 96 | } 97 | 98 | // 显示Popver选项 99 | presentPopover(myEvent) { 100 | let cb = { 101 | refresh: () => { 102 | this.reload(); 103 | }, 104 | close: () => { 105 | this.navCtrl.pop(); 106 | }, 107 | share: null 108 | }; 109 | 110 | if(this.browser.share) { 111 | cb.share = () => { 112 | this.share(); 113 | } 114 | } 115 | 116 | let popover = this.popoverCtrl.create('BrowserPopoverPage', { 117 | callback: cb 118 | }); 119 | popover.present({ 120 | ev: myEvent 121 | }); 122 | } 123 | 124 | // 重新加载页面 125 | reload() { 126 | let title = this.browser.title; 127 | let url = this.browser.secUrl; 128 | this.browser.title = '加载中'; 129 | this.browser.secUrl = this.sanitizer.bypassSecurityTrustResourceUrl(''); 130 | 131 | setTimeout(() => { 132 | this.browser.isLoaded = false; 133 | this.browser.progress = 0; 134 | if(!this.browser.proObj) { 135 | this.browser.proObj = document.getElementById('progress'); 136 | } 137 | this.onprogress(); 138 | this.browser.title = title; 139 | this.browser.secUrl = url; 140 | }, 10); 141 | } 142 | 143 | // 分享页面(作为popover的回调) 144 | share() { 145 | this.shareConfig.isShow = true; 146 | /*if(this.browser.share) { 147 | SocialSharing.share(this.browser.share.title, this.browser.share.content, '', this.browser.share.url).then(() => { 148 | 149 | }, (err) => { 150 | // Error! 151 | alert('错误:分享失败!' + err); 152 | }); 153 | }*/ 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/pages/gaodemap/gaodemap.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 高德地图 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /src/pages/gaodemap/gaodemap.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { IonicPageModule } from 'ionic-angular'; 3 | import { GaodemapPage } from './gaodemap'; 4 | 5 | @NgModule({ 6 | declarations: [ 7 | GaodemapPage, 8 | ], 9 | imports: [ 10 | IonicPageModule.forChild(GaodemapPage), 11 | ], 12 | }) 13 | export class GaodemapPageModule {} 14 | -------------------------------------------------------------------------------- /src/pages/gaodemap/gaodemap.scss: -------------------------------------------------------------------------------- 1 | page-gaodemap { 2 | #container{ 3 | width: 100%; 4 | height: 100%; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/pages/gaodemap/gaodemap.ts: -------------------------------------------------------------------------------- 1 | import { Component ,ViewChild ,ElementRef} from '@angular/core'; 2 | import { IonicPage, NavController, NavParams } from 'ionic-angular'; 3 | 4 | //引入html5定位 5 | import {GeolocationProvider} from '../../providers/geolocation/geolocation'; 6 | 7 | // gaode map 8 | declare var AMap; 9 | 10 | @IonicPage() 11 | @Component({ 12 | selector: 'page-gaodemap', 13 | templateUrl: 'gaodemap.html', 14 | }) 15 | export class GaodemapPage { 16 | 17 | 18 | @ViewChild('map2') map_container2: ElementRef; 19 | map: any;//地图对象 20 | 21 | constructor(public navCtrl: NavController, 22 | public html5Geolocation: GeolocationProvider, 23 | public navParams: NavParams) { 24 | } 25 | 26 | ionViewDidLoad() { 27 | console.log('ionViewDidLoad GaodemapPage'); 28 | } 29 | ionViewDidEnter() { 30 | this.load(); 31 | } 32 | load(){ 33 | this.map = new AMap.Map(this.map_container2.nativeElement, { 34 | view: new AMap.View2D({//创建地图二维视口 35 | center:[this.html5Geolocation.longitude,this.html5Geolocation.latitude], 36 | zoom: 16, //设置地图缩放级别 37 | rotateEnable: true, 38 | showBuildingBlock: true 39 | }) 40 | }); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/pages/index/index.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 首页 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/pages/index/index.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { IonicPageModule } from 'ionic-angular'; 3 | import { IndexPage } from './index'; 4 | 5 | @NgModule({ 6 | declarations: [ 7 | IndexPage, 8 | ], 9 | imports: [ 10 | IonicPageModule.forChild(IndexPage), 11 | ], 12 | }) 13 | export class IndexPageModule {} 14 | -------------------------------------------------------------------------------- /src/pages/index/index.scss: -------------------------------------------------------------------------------- 1 | page-index { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /src/pages/index/index.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {IonicPage, NavController, NavParams} from 'ionic-angular'; 3 | 4 | /** 5 | * Generated class for the IndexPage page. 6 | * 7 | * See https://ionicframework.com/docs/components/#navigation for more info on 8 | * Ionic pages and navigation. 9 | */ 10 | 11 | @IonicPage() 12 | @Component({ 13 | selector: 'page-index', 14 | templateUrl: 'index.html', 15 | }) 16 | export class IndexPage { 17 | constructor(public navCtrl: NavController, 18 | public navParams: NavParams) { 19 | } 20 | 21 | ionViewDidLoad() { 22 | console.log('ionViewDidLoad LoginPage'); 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/pages/page-demo/page-demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 演示 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | http请求 15 | 16 | http请求接口测试 17 | 结果:{{httpReturnData}} 18 | 19 | 20 | 21 | 22 | 定位 与 地图 23 | 24 | 25 | 26 | 27 | 纬度:{{geolocation.latitude}} 28 | 经度:{{geolocation.longitude}} 29 | 百度地图demo 30 | 高德地图demo 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 自定义组件父子通信 46 | 47 | 48 | 49 | 50 | 51 |

{{name}}

52 | 53 | 54 | 55 | 儿子传递给父亲事件的参数 :{{sonToFaterData}} 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 | -------------------------------------------------------------------------------- /src/pages/page-demo/page-demo.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { IonicPageModule } from 'ionic-angular'; 3 | import { PageDemoPage } from './page-demo'; 4 | 5 | 6 | import { ComponentsModule } from '../../components/components.module'; 7 | 8 | @NgModule({ 9 | declarations: [ 10 | PageDemoPage, 11 | ], 12 | imports: [ 13 | ComponentsModule, 14 | IonicPageModule.forChild(PageDemoPage), 15 | ], 16 | }) 17 | export class PageDemoPageModule {} 18 | -------------------------------------------------------------------------------- /src/pages/page-demo/page-demo.scss: -------------------------------------------------------------------------------- 1 | page-page-demo { 2 | input{ 3 | color:transparent; 4 | } 5 | input.input-demo{ 6 | color:transparent; 7 | text-shadow:0 0 0 red; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/pages/page-demo/page-demo.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 新建页面demo样本 3 | * - demo页面会引入democomponent教程 4 | * - demo页面会引入demoprovider教程 5 | * - demo页面会引入demopipe教程 6 | * - demo页面会引入第三方js教程,如jquery 7 | */ 8 | 9 | //引入需要的框架核心 10 | import {Component, Input} from '@angular/core'; 11 | import {IonicPage, NavController, NavParams} from 'ionic-angular'; 12 | 13 | 14 | //引入自定义的provider 15 | import {InterfaceListProvider} from '../../providers/interface-list/interface-list'; 16 | import {GeolocationProvider} from '../../providers/geolocation/geolocation'; 17 | 18 | 19 | 20 | /** 21 | * 引入自定义组件component 22 | * 1. 先新建组件component 23 | * ionic g component component-demo 24 | * 2. 在使用的页面的module中引入,例如这个页面,在 page-demo.module.ts 文件中引入 25 | * import { ComponentsModule } from '../../components/components.module'; 26 | * 3. 在 page-demo.module.ts 文件中 @NgModul e的 imports 数组中添加 27 | * ComponentsModule, 28 | * 4. 在html页面中使用 29 | * 30 | * 5. 关于父子组件之间的传值参考 案例组件 component-demo, 主要用到的修饰器 @Input() ,@Output 31 | * @Input() 用于父亲向儿子传递数据 32 | * @Output() 用于儿子向父亲传递事件 33 | */ 34 | 35 | /** 36 | * 引入第三方js教程,如jquery 37 | * 1. 先在入口index.html文件引入js 38 | * 39 | * 2. 在使用的页面申明 40 | * declare var $: any; 41 | * 3. 直接使用 42 | */ 43 | declare var $: any; 44 | 45 | 46 | @IonicPage() 47 | @Component({ 48 | selector: 'page-page-demo', 49 | templateUrl: 'page-demo.html', 50 | }) 51 | export class PageDemoPage { 52 | 53 | name: string = 'wang'; 54 | //父子组件通信:儿子传给父亲的数据 55 | sonToFaterData: string; 56 | //http请求返回结果 57 | httpReturnData:string; 58 | 59 | constructor(public navCtrl: NavController, 60 | public interface_lists: InterfaceListProvider, 61 | public geolocation: GeolocationProvider, 62 | public navParams: NavParams) { 63 | } 64 | 65 | ionViewDidLoad() { 66 | this.jqueryDemo(); 67 | 68 | 69 | } 70 | 71 | //接口测试 72 | httpTest() { 73 | this.interface_lists.httpTset().then((returnData) => { 74 | console.log(returnData); 75 | this.httpReturnData=JSON.stringify(returnData); 76 | }) 77 | } 78 | getGeolocation(){ 79 | // this.geolocation.getGeolocation(); 80 | this.geolocation.watchPosition(); 81 | } 82 | 83 | getTpMap(){ 84 | // this.navCtrl.push('BaiduMapPage'); 85 | this.navCtrl.push('GaodemapPage'); 86 | } 87 | 88 | //使用jquery的案例 89 | jqueryDemo() { 90 | $('.jqueryClass1').on('click', () => { 91 | $(this).html('jquery button click'); 92 | $(this).css('color', 'red'); 93 | console.log('click'); 94 | }); 95 | $('.jqueryClass2').on('click', function () { 96 | $(this).html('jquery button click'); 97 | $(this).css('color', 'red'); 98 | console.log('click'); 99 | }); 100 | } 101 | 102 | 103 | toSonData(){ 104 | this.name='你好 世界'; 105 | } 106 | 107 | //子组件事件传递给父亲,父亲接受的事件回调 108 | sonToFaterEventCallback(e) { 109 | console.log(e.sonToFaterData); //儿子传过来事件的参数 110 | this.sonToFaterData = e.sonToFaterData; 111 | } 112 | 113 | 114 | openBrower(){ 115 | this.navCtrl.push('BrowserPage', { 116 | browser: { 117 | title: '页面名称', 118 | // url: '这里放置访问的页面链接' 119 | url: 'https://www.baidu.com' 120 | } 121 | }); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/pages/tabs/tabs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/pages/tabs/tabs.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | templateUrl: 'tabs.html' 5 | }) 6 | export class TabsPage { 7 | 8 | tab1Root = 'IndexPage'; 9 | tab2Root = 'PageDemoPage'; 10 | 11 | constructor() { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/pipes/pipe-demo/pipe-demo.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | 3 | /** 4 | * Generated class for the PipeDemoPipe pipe. 5 | * 6 | * See https://angular.io/api/core/Pipe for more info on Angular Pipes. 7 | */ 8 | @Pipe({ 9 | name: 'pipeDemo', 10 | }) 11 | export class PipeDemoPipe implements PipeTransform { 12 | /** 13 | * Takes a value and makes it lowercase. 14 | */ 15 | transform(value: string, ...args) { 16 | return value.toLowerCase(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/pipes/pipes.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { PipeDemoPipe } from './pipe-demo/pipe-demo'; 3 | @NgModule({ 4 | declarations: [PipeDemoPipe], 5 | imports: [], 6 | exports: [PipeDemoPipe] 7 | }) 8 | export class PipesModule {} 9 | -------------------------------------------------------------------------------- /src/providers/geolocation/geolocation.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | 3 | /** 4 | * 定位服务 5 | */ 6 | @Injectable() 7 | export class GeolocationProvider { 8 | constructor() { 9 | // console.log('Hello GeolocationProvider Provider'); 10 | this.watchPosition(); 11 | } 12 | 13 | latitude:number; //十进制数的纬度 14 | longitude:number; //十进制数的经度 15 | 16 | /** 17 | * HTML5 Geolocation(地理定位)定位用户的位置 18 | * Api : navigator.geolocation.getCurrentPosition(on_success, on_error, options); 19 | * 1.位置服务用于估计您所在位置的本地网络信息包括:有关可见 WiFi 接入点的信息(包括信号强度)、有关您本地路由器的信息、您计算机的 IP 地址。位置服务的准确度和覆盖范围因位置不同而异。 20 | * 2.总的来说,在PC的浏览器中 HTML5 的地理位置功能获取的位置精度不够高,如果借助这个 HTML5 特性做一个城市天气预报是绰绰有余,但如果是做一个地图应用,那误差还是太大了。 21 | * 3.不过,如果是移动设备上的 HTML5 应用,可以通过设置 enableHighAcuracy 参数为 true,调用设备的 GPS 定位来获取高精度的地理位置信息。 22 | */ 23 | getGeolocation() :any{ 24 | if (navigator.geolocation) { 25 | navigator.geolocation.getCurrentPosition((position)=>{ 26 | this.showPosition(position) 27 | }, (err)=>this.locationError(err), { 28 | // true获取高精度的位置,默认为false 29 | enableHighAccuracy: true, 30 | // 指定获取地理位置的超时时间,默认不限时,单位为毫秒 31 | timeout: 5000, 32 | // 最长有效期,在重复获取地理位置时,此参数指定多久再次获取位置。 33 | maximumAge: 3000 34 | }); 35 | } 36 | else { 37 | console.log("不支持定位"); 38 | } 39 | } 40 | 41 | /** 42 | * 监听地理位置变化 43 | * Api : navigator.geolocation.watchPosition(on_success, on_error, options); 44 | * watchPosition() - 返回用户的当前位置,并继续返回用户移动时的更新位置(就像汽车上的 GPS)。 45 | * clearWatch() - 停止 watchPosition() 方法 46 | * 下面的例子展示 watchPosition() 方法。您需要一台精确的 GPS 设备来测试该例(比如 iPhone): 47 | */ 48 | watchPosition(){ 49 | if (navigator.geolocation) { 50 | navigator.geolocation.watchPosition((position)=>{ 51 | this.showPosition(position) 52 | }, (err)=>this.locationError(err), { 53 | // true获取高精度的位置,默认为false 54 | enableHighAccuracy: true, 55 | // 指定获取地理位置的超时时间,默认不限时,单位为毫秒 56 | timeout: 5000, 57 | // 最长有效期,在重复获取地理位置时,此参数指定多久再次获取位置。 58 | maximumAge: 3000 59 | }); 60 | }else{ 61 | console.log("不支持定位"); 62 | } 63 | 64 | } 65 | 66 | 67 | 68 | /** 69 | * 参数1 : 成功回调 70 | */ 71 | showPosition(position) :any{ 72 | console.log(typeof position.coords.latitude); 73 | console.log(position.coords.latitude); 74 | console.log(position.coords.longitude); 75 | this.latitude = position.coords.latitude; 76 | this.longitude = position.coords.longitude; 77 | } 78 | 79 | 80 | /** 81 | * 参数2: 失败回调 82 | */ 83 | locationError(error) { 84 | switch (error.code) { 85 | case error.TIMEOUT: 86 | this.showError("A timeout occured! Please try again!"); 87 | break; 88 | case error.POSITION_UNAVAILABLE: 89 | this.showError('We can\'t detect your location. Sorry!'); 90 | break; 91 | case error.PERMISSION_DENIED: 92 | this.showError('Please allow geolocation access for this to work.'); 93 | break; 94 | case error.UNKNOWN_ERROR: 95 | this.showError('An unknown error occured!'); 96 | break; 97 | } 98 | } 99 | 100 | showError(err) { 101 | console.log(err); 102 | } 103 | 104 | 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/providers/http-ser/http-ser.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import {Http, Response, Headers, RequestOptions} from '@angular/http'; 3 | import 'rxjs/add/operator/map'; 4 | import 'rxjs/add/operator/toPromise'; 5 | 6 | /** 7 | * HTTP请求服务 8 | */ 9 | @Injectable() 10 | export class HttpSerProvider { 11 | 12 | constructor(public http: Http) { 13 | // console.log('Hello HttpSerProvider Provider'); 14 | } 15 | 16 | /** 17 | * get方式请求 18 | * @param {string} url //url 19 | * @param paramObj //json对象 如:{name:'大见',age:'23'} 20 | * @return {Promise} 21 | */ 22 | get(url:string, paramObj:any = {}) { 23 | let timestamp = Math.floor(new Date().getTime() / 1000 - 1420070400).toString(); //获取当前时间 减 2015年1月1日的 时间戳 24 | let headers = new Headers({'timestamp': timestamp}); 25 | let options = new RequestOptions({headers: headers}); 26 | return this.http.get(url + this.toQueryString(paramObj),options) 27 | .toPromise() 28 | .then(this.extractData) 29 | .catch(this.handleError); 30 | } 31 | 32 | /** 33 | * post方式请求 34 | * @param {string} url 35 | * @param body //如:paramObj:{name:'大见',age:'23'} 36 | * @param {string} contentType //post请求的编码方式 application/x-www-form-urlencoded multipart/form-data application/json text/xml 37 | * @return {Promise} 38 | */ 39 | post(url:string, body:any = {}, contentType:string="application/x-www-form-urlencoded") { 40 | let headers = new Headers({'Content-Type':contentType}); 41 | let options = new RequestOptions({headers: headers}); 42 | return this.http.post(url, this.toBodyString(body),options) 43 | .toPromise() 44 | .then(this.extractData) 45 | .catch(this.handleError); 46 | } 47 | 48 | 49 | 50 | /** 51 | * get请求参数处理 52 | * 对于get方法来说,都是把数据串联在请求的url后面作为参数,如果url中出现中文或其它特殊字符的话,很常见的一个乱码问题就要出现了 53 | * url拼接完成后,浏览器会对url进行URL encode,然后发送给服务器,URL encode的过程就是把部分url做为字符,按照某种编码方式(如:utf-8,gbk等)编码成二进制的字节码 54 | * 不同的浏览器有不同的做法,中文版的浏览器一般会默认的使用GBK,通过设置浏览器也可以使用UTF-8,可能不同的用户就有不同的浏览器设置,也就造成不同的编码方式, 55 | * 所以通常做法都是先把url里面的中文或特殊字符用 javascript做URL encode,然后再拼接url提交数据,也就是替浏览器做了URL encode,好处就是网站可以统一get方法提交数据的编码方式。 56 | * @param obj 参数对象 57 | * @return {string} 参数字符串 58 | * @example 59 | * 声明: var obj= {'name':'大见',age:23}; 60 | * 调用: toQueryString(obj); 61 | * 返回: "?name=%E5%B0%8F%E5%86%9B&age=23" 62 | */ 63 | private toQueryString(obj) { 64 | let ret = []; 65 | for (let key in obj) { 66 | key = encodeURIComponent(key); 67 | let values = obj[key]; 68 | if (values && values.constructor == Array) {//数组 69 | let queryValues = []; 70 | for (let i = 0, len = values.length, value; i < len; i++) { 71 | value = values[i]; 72 | queryValues.push(this.toQueryPair(key, value)); 73 | } 74 | ret = ret.concat(queryValues); 75 | } else { //字符串 76 | ret.push(this.toQueryPair(key, values)); 77 | } 78 | } 79 | return '?' + ret.join('&'); 80 | } 81 | 82 | /** 83 | * post请求参数处理 84 | * @param obj 85 | * @return {string} 86 | * 声明: var obj= {'name':'大见',age:23}; 87 | * 调用: toQueryString(obj); 88 | * 返回: "name=%E5%B0%8F%E5%86%9B&age=23" 89 | */ 90 | private toBodyString(obj) { 91 | let ret = []; 92 | for (let key in obj) { 93 | key = encodeURIComponent(key); 94 | // key = key; 95 | let values = obj[key]; 96 | if (values && values.constructor == Array) {//数组 97 | let queryValues = []; 98 | for (let i = 0, len = values.length, value; i < len; i++) { 99 | value = values[i]; 100 | queryValues.push(this.toQueryPair(key, value)); 101 | } 102 | ret = ret.concat(queryValues); 103 | } else { //字符串 104 | ret.push(this.toQueryPair(key, values)); 105 | } 106 | } 107 | return ret.join('&'); 108 | } 109 | 110 | private toQueryPair(key, value) { 111 | if (typeof value == 'undefined') { 112 | return key; 113 | } 114 | return key + '=' + encodeURIComponent(value === null ? '' : String(value)); 115 | // return key + '=' +(value === null ? '' : String(value)); 116 | } 117 | 118 | private toSignPair(key, value) { 119 | return key + '=' + (value === null ? '' : String(value)); 120 | } 121 | 122 | private extractData(res:Response) { 123 | let body = res.json(); 124 | return body || {}; 125 | } 126 | 127 | private handleError(error:Response | any) { 128 | let errMsg:string; 129 | if (error instanceof Response) { 130 | const body = error.json() || ''; 131 | const err = body.error || JSON.stringify(body); 132 | errMsg = `${error.status} - ${error.statusText || ''} ${err}`; 133 | } else { 134 | errMsg = error.message ? error.message : error.toString(); 135 | } 136 | console.error(errMsg); 137 | return Promise.reject(errMsg); 138 | } 139 | 140 | 141 | 142 | } 143 | -------------------------------------------------------------------------------- /src/providers/interface-list/interface-list.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpSerProvider } from '../http-ser/http-ser'; 3 | import {APP_SERVE_URL} from '../../app/app.config'; 4 | 5 | /** 6 | * App接口列表 7 | */ 8 | @Injectable() 9 | export class InterfaceListProvider { 10 | 11 | constructor(private httpser:HttpSerProvider) { 12 | console.log('Hello InterfaceListProvider Provider'); 13 | } 14 | /** 15 | * 接口测试 16 | * @param data:{version:1} 17 | * @returns Promise 18 | */ 19 | httpTset() { 20 | let url = APP_SERVE_URL + "/userLoginRegisterjfsc/selecIntegralApi"; 21 | return this.httpser.get(url, {userId:1}); 22 | } 23 | 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/providers/pop-ser/pop-ser.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {LoadingController, AlertController, ModalController, ToastController} from 'ionic-angular'; 3 | 4 | /* 5 | Generated class for the PopSerProvider provider. 6 | 7 | See https://angular.io/guide/dependency-injection for more info on providers 8 | and Angular DI. 9 | */ 10 | /** 11 | * 遮罩层服务 12 | * 13 | */ 14 | @Injectable() 15 | export class PopSerProvider { 16 | private load: any; 17 | constructor(public loadingCtrl: LoadingController, 18 | public alertCtrl: AlertController, 19 | public toastCtrl: ToastController, 20 | public modalCtrl: ModalController) { 21 | console.log('PopSerProvider Provider'); 22 | } 23 | 24 | /** 25 | * alert弹窗 26 | * http://ionicframework.com/docs/api/components/alert/AlertController/ 27 | */ 28 | alert(content, callback = () => { 29 | }) { 30 | let alert = this.alertCtrl.create({ 31 | title: '提示', 32 | message: '
' + content + '
', 33 | enableBackdropDismiss: false, 34 | cssClass: '', 35 | buttons: [ 36 | { 37 | text: "好的", 38 | cssClass: 'pop_btn', 39 | handler: () => { 40 | if (callback != undefined && callback != null && typeof callback == 'function') { 41 | callback(); 42 | } 43 | } 44 | }] 45 | }); 46 | alert.present(); 47 | } 48 | 49 | /** 50 | * 自定义alert弹窗- 51 | */ 52 | alertDIY(obj, ok_callback: any = () => { 53 | }) { 54 | let confirm_diy = this.alertCtrl.create({ 55 | title: obj.title || '
提示
', 56 | subTitle: obj.subTitle, 57 | message: obj.content, 58 | cssClass: obj.cssClass, 59 | enableBackdropDismiss: false, //是否点击背景关闭弹窗 60 | buttons: [ 61 | { 62 | text: obj.okText || '确定', 63 | cssClass: 'pop_btn', 64 | handler: () => { 65 | if (ok_callback != undefined && ok_callback != null && typeof ok_callback == 'function') { 66 | ok_callback(); 67 | } 68 | } 69 | } 70 | ] 71 | }); 72 | confirm_diy.present(); 73 | } 74 | 75 | /** 76 | * confirm确认框 77 | */ 78 | confirm(content, ok_callback = () => { 79 | }) { 80 | let alert = this.alertCtrl.create({ 81 | title: '
提示
', 82 | subTitle: '', 83 | message: content, 84 | cssClass: '', 85 | enableBackdropDismiss: false, //是否点击背景关闭弹窗 86 | buttons: [ 87 | { 88 | text: '取消', 89 | role: 'cancel', 90 | }, 91 | { 92 | text: '确定', 93 | cssClass: 'pop_btn', 94 | handler: () => { 95 | if (ok_callback != undefined && ok_callback != null && typeof ok_callback == 'function') { 96 | ok_callback(); 97 | } 98 | } 99 | } 100 | ] 101 | }); 102 | alert.present(); 103 | } 104 | 105 | /** 106 | * 自定义confirm确认框 107 | */ 108 | confirmDIY(obj, esc_callback: any = () => { 109 | }, ok_callback: any = () => { 110 | }) { 111 | let confirm_diy = this.alertCtrl.create({ 112 | title: obj.title || '
', 113 | subTitle: obj.subTitle || '', 114 | cssClass: obj.cssClass || '', 115 | message: '
' + obj.content + '
', 116 | enableBackdropDismiss: false, 117 | buttons: [ 118 | { 119 | text: obj.escText || '取消', 120 | handler: () => { 121 | if (esc_callback != undefined && esc_callback != null && typeof esc_callback == 'function') { 122 | esc_callback(); 123 | } 124 | } 125 | }, 126 | { 127 | text: obj.okText || '确定', 128 | cssClass: 'pop_btn', 129 | handler: () => { 130 | if (ok_callback != undefined && ok_callback != null && typeof ok_callback == 'function') { 131 | ok_callback(); 132 | } 133 | } 134 | } 135 | ] 136 | }); 137 | confirm_diy.present(); 138 | } 139 | 140 | 141 | /** 142 | * toast短暂提示 (支持自定义) 143 | * http://ionicframework.com/docs/api/components/toast/ToastController/ 144 | * @param {string} content 145 | * @param {string} position //"top", "middle", "bottom". 146 | * @param {string} cssClass 147 | * @param {number} duration 148 | */ 149 | toast(content:string,position:string='bottom',cssClass:string='',duration:number=3000) { 150 | let toast = this.toastCtrl.create({ 151 | message: content, 152 | duration: 3000, 153 | position: position, //"top", "middle", "bottom". 154 | cssClass: cssClass, 155 | showCloseButton: false, 156 | closeButtonText: "关闭", 157 | dismissOnPageChange: false, //当页面变化时是否dismiss 158 | }); 159 | toast.onDidDismiss(() => { 160 | console.log('Dismissed toast'); 161 | }); 162 | toast.present(); 163 | } 164 | 165 | /** 166 | * 拨打号码弹窗 167 | */ 168 | callPop(obj, esc_callback: any = () => { 169 | }, ok_callback: any = () => { 170 | }) { 171 | setTimeout(() => {//延迟几秒可以等html反应,这样获取的高度才准确 172 | let test = document.getElementsByClassName("pop_btn")[0]; 173 | test.innerHTML = " 继续呼叫 "; 174 | }, 3); 175 | let confirm_diy = this.alertCtrl.create({ 176 | title: obj.title || '
', 177 | subTitle: obj.subTitle, 178 | cssClass: "call", 179 | message: '
' + obj.content + '
', 180 | enableBackdropDismiss: false, 181 | buttons: [ 182 | { 183 | text: obj.escText || '取消', 184 | handler: () => { 185 | if (esc_callback != undefined && esc_callback != null && typeof esc_callback == 'function') { 186 | esc_callback(); 187 | } 188 | } 189 | }, 190 | { 191 | text: obj.okText || '确定', 192 | cssClass: 'pop_btn', 193 | handler: () => { 194 | if (ok_callback != undefined && ok_callback != null && typeof ok_callback == 'function') { 195 | ok_callback(); 196 | } 197 | } 198 | } 199 | ] 200 | }); 201 | confirm_diy.present(); 202 | } 203 | 204 | /** 205 | * loading加载动画 206 | * http://ionicframework.com/docs/api/components/loading/LoadingController/ 207 | * @param {string} op // 取值:open hide 208 | * @param {string} content 209 | * @param {string} spinner 动画SVG // 取值:ios ios-small bubbles circles crescent dots 210 | * @param {string} css 211 | * @param {boolean} showBackdrop 是否有黑色遮罩 212 | */ 213 | loading(op:string, content: string ='', spinner:string='ios-small',css: string='',showBackdrop:boolean=true) { 214 | if (op == 'hide') { 215 | if (this.load) { 216 | this.load.dismiss(); 217 | } 218 | } else { 219 | this.load = this.loadingCtrl.create({ 220 | spinner: spinner, 221 | content:content, 222 | cssClass: css, 223 | showBackdrop:showBackdrop, //是否有黑色遮罩 224 | enableBackdropDismiss:false, 225 | dismissOnPageChange:false, 226 | // duration:3000 227 | }); 228 | this.load.present(); 229 | setTimeout(() => { 230 | this.load.dismiss(); 231 | }, 10000); 232 | } 233 | this.load.onDidDismiss(() => { 234 | console.log('Dismissed loading'); 235 | }); 236 | } 237 | 238 | 239 | } 240 | -------------------------------------------------------------------------------- /src/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check out https://googlechrome.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.cacheFirst); 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 | // Ionic Variables and Theming. For more info, please see: 2 | // http://ionicframework.com/docs/theming/ 3 | 4 | // Font path is used to include ionicons, 5 | // roboto, and noto sans fonts 6 | $font-path: "../assets/fonts"; 7 | 8 | 9 | // The app direction is used to include 10 | // rtl styles in your app. For more info, please see: 11 | // http://ionicframework.com/docs/theming/rtl-support/ 12 | $app-direction: ltr; 13 | 14 | 15 | @import "ionic.globals"; 16 | 17 | 18 | // Shared Variables 19 | // -------------------------------------------------- 20 | // To customize the look and feel of this app, you can override 21 | // the Sass variables found in Ionic's source scss files. 22 | // To view all the possible Ionic variables, see: 23 | // http://ionicframework.com/docs/theming/overriding-ionic-variables/ 24 | 25 | 26 | 27 | 28 | // Named Color Variables 29 | // -------------------------------------------------- 30 | // Named colors makes it easy to reuse colors on various components. 31 | // It's highly recommended to change the default colors 32 | // to match your app's branding. Ionic uses a Sass map of 33 | // colors so you can add, rename and remove colors as needed. 34 | // The "primary" color is the only required color in the map. 35 | 36 | $colors: ( 37 | primary: #488aff, 38 | secondary: #32db64, 39 | danger: #f53d3d, 40 | light: #f4f4f4, 41 | dark: #222 42 | ); 43 | 44 | 45 | // App iOS Variables 46 | // -------------------------------------------------- 47 | // iOS only Sass variables can go here 48 | 49 | 50 | 51 | 52 | // App Material Design Variables 53 | // -------------------------------------------------- 54 | // Material Design only Sass variables can go here 55 | 56 | 57 | 58 | 59 | // App Windows Variables 60 | // -------------------------------------------------- 61 | // Windows only Sass variables can go here 62 | 63 | 64 | 65 | 66 | // App Theme 67 | // -------------------------------------------------- 68 | // Ionic apps can have different themes applied, which can 69 | // then be future customized. This import comes last 70 | // so that the above variables are used and Ionic's 71 | // default are overridden. 72 | 73 | @import "ionic.theme.default"; 74 | 75 | 76 | // Ionicons 77 | // -------------------------------------------------- 78 | // The premium icon font for Ionic. For more info, please see: 79 | // http://ionicframework.com/docs/ionicons/ 80 | 81 | @import "ionic.ionicons"; 82 | 83 | 84 | // Fonts 85 | // -------------------------------------------------- 86 | 87 | @import "roboto"; 88 | @import "noto-sans"; 89 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------