New file |
| | |
| | | # EditorConfig helps developers define and maintain consistent coding styles between different editors and IDEs |
| | | # editorconfig.org |
| | | |
| | | root = true |
| | | |
| | | [*] |
| | | indent_style = space |
| | | indent_size = 2 |
| | | |
| | | # We recommend you to keep these unchanged |
| | | end_of_line = lf |
| | | charset = utf-8 |
| | | trim_trailing_whitespace = true |
| | | insert_final_newline = true |
| | | |
| | | [*.md] |
| | | trim_trailing_whitespace = false |
New file |
| | |
| | | # Specifies intentionally untracked files to ignore when using Git |
| | | # http://git-scm.com/docs/gitignore |
| | | |
| | | *~ |
| | | *.sw[mnpcod] |
| | | *.log |
| | | *.tmp |
| | | *.tmp.* |
| | | log.txt |
| | | *.sublime-project |
| | | *.sublime-workspace |
| | | .vscode/ |
| | | npm-debug.log* |
| | | |
| | | .idea/ |
| | | .sass-cache/ |
| | | .tmp/ |
| | | .versions/ |
| | | coverage/ |
| | | dist/ |
| | | node_modules/ |
| | | tmp/ |
| | | temp/ |
| | | hooks/ |
| | | platforms/ |
| | | plugins/ |
| | | plugins/android.json |
| | | plugins/ios.json |
| | | www/ |
| | | $RECYCLE.BIN/ |
| | | |
| | | .DS_Store |
| | | Thumbs.db |
| | | UserInterfaceState.xcuserstate |
New file |
| | |
| | | MIT License |
| | | |
| | | Copyright (c) 2017 kinglionsoft |
| | | |
| | | Permission is hereby granted, free of charge, to any person obtaining a copy |
| | | of this software and associated documentation files (the "Software"), to deal |
| | | in the Software without restriction, including without limitation the rights |
| | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | | copies of the Software, and to permit persons to whom the Software is |
| | | furnished to do so, subject to the following conditions: |
| | | |
| | | The above copyright notice and this permission notice shall be included in all |
| | | copies or substantial portions of the Software. |
| | | |
| | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| | | SOFTWARE. |
New file |
| | |
| | | <?xml version='1.0' encoding='utf-8'?> |
| | | <widget id="io.ionic.starter" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> |
| | | <name>ykseed</name> |
| | | <description>An awesome Ionic/Cordova app.</description> |
| | | <author email="hi@ionicframework" href="http://ionicframework.com/">Ionic Framework Team</author> |
| | | <content src="index.html" /> |
| | | <access origin="*" /> |
| | | <allow-navigation href="http://ionic.local/*" /> |
| | | <allow-intent href="http://*/*" /> |
| | | <allow-intent href="https://*/*" /> |
| | | <allow-intent href="tel:*" /> |
| | | <allow-intent href="sms:*" /> |
| | | <allow-intent href="mailto:*" /> |
| | | <allow-intent href="geo:*" /> |
| | | <preference name="webviewbounce" value="false" /> |
| | | <preference name="UIWebViewBounce" value="false" /> |
| | | <preference name="DisallowOverscroll" value="true" /> |
| | | <preference name="android-minSdkVersion" value="16" /> |
| | | <preference name="BackupWebStorage" value="none" /> |
| | | <preference name="SplashMaintainAspectRatio" value="true" /> |
| | | <preference name="FadeSplashScreenDuration" value="300" /> |
| | | |
| | | <!-- |
| | | Change these to configure how the splashscreen displays and fades in/out. |
| | | More info here: https://github.com/apache/cordova-plugin-splashscreen |
| | | --> |
| | | <preference name="SplashShowOnlyFirstTime" value="false" /> |
| | | <preference name="SplashScreen" value="screen" /> |
| | | <preference name="SplashScreenDelay" value="3000" /> |
| | | <platform name="android"> |
| | | <allow-intent href="market:*" /> |
| | | <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" /> |
| | | <icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" /> |
| | | <icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png" /> |
| | | <icon density="xhdpi" src="resources/android/icon/drawable-xhdpi-icon.png" /> |
| | | <icon density="xxhdpi" src="resources/android/icon/drawable-xxhdpi-icon.png" /> |
| | | <icon density="xxxhdpi" src="resources/android/icon/drawable-xxxhdpi-icon.png" /> |
| | | <splash density="land-ldpi" src="resources/android/splash/drawable-land-ldpi-screen.png" /> |
| | | <splash density="land-mdpi" src="resources/android/splash/drawable-land-mdpi-screen.png" /> |
| | | <splash density="land-hdpi" src="resources/android/splash/drawable-land-hdpi-screen.png" /> |
| | | <splash density="land-xhdpi" src="resources/android/splash/drawable-land-xhdpi-screen.png" /> |
| | | <splash density="land-xxhdpi" src="resources/android/splash/drawable-land-xxhdpi-screen.png" /> |
| | | <splash density="land-xxxhdpi" src="resources/android/splash/drawable-land-xxxhdpi-screen.png" /> |
| | | <splash density="port-ldpi" src="resources/android/splash/drawable-port-ldpi-screen.png" /> |
| | | <splash density="port-mdpi" src="resources/android/splash/drawable-port-mdpi-screen.png" /> |
| | | <splash density="port-hdpi" src="resources/android/splash/drawable-port-hdpi-screen.png" /> |
| | | <splash density="port-xhdpi" src="resources/android/splash/drawable-port-xhdpi-screen.png" /> |
| | | <splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png" /> |
| | | <splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png" /> |
| | | </platform> |
| | | <platform name="ios"> |
| | | <allow-intent href="itms:*" /> |
| | | <allow-intent href="itms-apps:*" /> |
| | | <icon height="57" src="resources/ios/icon/icon.png" width="57" /> |
| | | <icon height="114" src="resources/ios/icon/icon@2x.png" width="114" /> |
| | | <icon height="40" src="resources/ios/icon/icon-40.png" width="40" /> |
| | | <icon height="80" src="resources/ios/icon/icon-40@2x.png" width="80" /> |
| | | <icon height="120" src="resources/ios/icon/icon-40@3x.png" width="120" /> |
| | | <icon height="50" src="resources/ios/icon/icon-50.png" width="50" /> |
| | | <icon height="100" src="resources/ios/icon/icon-50@2x.png" width="100" /> |
| | | <icon height="60" src="resources/ios/icon/icon-60.png" width="60" /> |
| | | <icon height="120" src="resources/ios/icon/icon-60@2x.png" width="120" /> |
| | | <icon height="180" src="resources/ios/icon/icon-60@3x.png" width="180" /> |
| | | <icon height="72" src="resources/ios/icon/icon-72.png" width="72" /> |
| | | <icon height="144" src="resources/ios/icon/icon-72@2x.png" width="144" /> |
| | | <icon height="76" src="resources/ios/icon/icon-76.png" width="76" /> |
| | | <icon height="152" src="resources/ios/icon/icon-76@2x.png" width="152" /> |
| | | <icon height="167" src="resources/ios/icon/icon-83.5@2x.png" width="167" /> |
| | | <icon height="29" src="resources/ios/icon/icon-small.png" width="29" /> |
| | | <icon height="58" src="resources/ios/icon/icon-small@2x.png" width="58" /> |
| | | <icon height="87" src="resources/ios/icon/icon-small@3x.png" width="87" /> |
| | | <splash height="1136" src="resources/ios/splash/Default-568h@2x~iphone.png" width="640" /> |
| | | <splash height="1334" src="resources/ios/splash/Default-667h.png" width="750" /> |
| | | <splash height="2208" src="resources/ios/splash/Default-736h.png" width="1242" /> |
| | | <splash height="1242" src="resources/ios/splash/Default-Landscape-736h.png" width="2208" /> |
| | | <splash height="1536" src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048" /> |
| | | <splash height="2048" src="resources/ios/splash/Default-Landscape@~ipadpro.png" width="2732" /> |
| | | <splash height="768" src="resources/ios/splash/Default-Landscape~ipad.png" width="1024" /> |
| | | <splash height="2048" src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536" /> |
| | | <splash height="2732" src="resources/ios/splash/Default-Portrait@~ipadpro.png" width="2048" /> |
| | | <splash height="1024" src="resources/ios/splash/Default-Portrait~ipad.png" width="768" /> |
| | | <splash height="960" src="resources/ios/splash/Default@2x~iphone.png" width="640" /> |
| | | <splash height="480" src="resources/ios/splash/Default~iphone.png" width="320" /> |
| | | </platform> |
| | | <plugin name="ionic-plugin-keyboard" spec="~2.2.1" /> |
| | | <plugin name="cordova-plugin-whitelist" spec="1.3.1" /> |
| | | <plugin name="cordova-plugin-console" spec="1.0.5" /> |
| | | <plugin name="cordova-plugin-statusbar" spec="2.2.2" /> |
| | | <plugin name="cordova-plugin-device" spec="1.1.4" /> |
| | | <plugin name="cordova-plugin-splashscreen" spec="~4.0.1" /> |
| | | <plugin name="cordova-plugin-camera" spec="~2.4.1" /> |
| | | </widget> |
New file |
| | |
| | | const path = require('path'); |
| | | const defaults = require('@ionic/app-scripts/config/optimization.config'); |
| | | |
| | | module.exports = function () { |
| | | |
| | | if (!defaults.resolve.alias) { |
| | | defaults.resolve.alias = {}; |
| | | } |
| | | defaults.resolve.alias.kl = path.resolve('src/kl'); |
| | | |
| | | return defaults; |
| | | }; |
New file |
| | |
| | | const path = require('path'); |
| | | const defaults = require('@ionic/app-scripts/config/webpack.config'); |
| | | |
| | | module.exports = function () { |
| | | |
| | | if (!defaults.resolve.alias) { |
| | | defaults.resolve.alias = {}; |
| | | } |
| | | defaults.resolve.alias.kl = path.resolve('src/kl'); |
| | | |
| | | return defaults; |
| | | }; |
New file |
| | |
| | | { |
| | | "name": "ionic-seed3", |
| | | "app_id": "", |
| | | "type": "ionic-angular", |
| | | "integrations": {} |
| | | } |
New file |
| | |
| | | { |
| | | "name": "xsmax-app", |
| | | "version": "0.0.1", |
| | | "author": "Ionic Framework", |
| | | "homepage": "http://ionicframework.com/", |
| | | "private": true, |
| | | "config": { |
| | | "ionic_webpack": "./config/webpack.config.js", |
| | | "ionic_optimization": "./config/optimization.config.js" |
| | | }, |
| | | "scripts": { |
| | | "clean": "ionic-app-scripts clean", |
| | | "build": "ionic-app-scripts build", |
| | | "lint": "ionic-app-scripts lint", |
| | | "ionic:build": "ionic-app-scripts build", |
| | | "ionic:serve": "ionic-app-scripts serve" |
| | | }, |
| | | "dependencies": { |
| | | "@angular/common": "4.1.3", |
| | | "@angular/compiler": "4.1.3", |
| | | "@angular/compiler-cli": "4.1.3", |
| | | "@angular/core": "4.1.3", |
| | | "@angular/forms": "4.1.3", |
| | | "@angular/http": "4.1.3", |
| | | "@angular/platform-browser": "4.1.3", |
| | | "@angular/platform-browser-dynamic": "4.1.3", |
| | | "@ionic-native/camera": "^3.12.1", |
| | | "@ionic-native/core": "3.12.1", |
| | | "@ionic-native/splash-screen": "3.12.1", |
| | | "@ionic-native/status-bar": "3.12.1", |
| | | "@ionic/storage": "2.0.1", |
| | | "ionic-angular": "3.6.0", |
| | | "ionicons": "3.0.0", |
| | | "moment": "^2.18.1", |
| | | "rxjs": "5.4.0", |
| | | "sw-toolbox": "3.6.0", |
| | | "zone.js": "0.8.12" |
| | | }, |
| | | "devDependencies": { |
| | | "@ionic/app-scripts": "2.1.3", |
| | | "ionic": "^3.9.2", |
| | | "tslint-ionic-rules": "^0.0.11", |
| | | "typescript": "2.3.4" |
| | | }, |
| | | "description": "ykseed: An Ionic project@3.6.0" |
| | | } |
New file |
| | |
| | | #!/bin/bash |
| | | ionic serve |
New file |
| | |
| | | import { Component, ViewChild } from '@angular/core'; |
| | | import { Platform, Nav } from 'ionic-angular'; |
| | | import { StatusBar } from '@ionic-native/status-bar'; |
| | | import { SplashScreen } from '@ionic-native/splash-screen'; |
| | | import { PlatformService } from 'kl/core'; |
| | | |
| | | @Component({ |
| | | templateUrl: 'app.html' |
| | | }) |
| | | export class MyApp { |
| | | rootPage: any = 'maintabs'; |
| | | @ViewChild(Nav) nav: Nav; |
| | | |
| | | constructor( |
| | | platform: Platform, |
| | | private statusBar: StatusBar, |
| | | private splashScreen: SplashScreen, |
| | | private platformService: PlatformService) { |
| | | platform.ready().then(() => { |
| | | this.splashScreen.hide(); |
| | | |
| | | if (platform.is('ios') || platform.is('android')) { |
| | | this.statusBar.styleDefault(); |
| | | } |
| | | // 注册返回按键事件 |
| | | this.platformService.rootNav = this.nav; |
| | | this.platformService.registerBackButton(); |
| | | }); |
| | | } |
| | | } |
New file |
| | |
| | | <ion-nav [root]="rootPage"></ion-nav> |
New file |
| | |
| | | import { NgModule, ErrorHandler } from '@angular/core'; |
| | | import { BrowserModule } from '@angular/platform-browser'; |
| | | import { HttpModule } from '@angular/http'; |
| | | |
| | | import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular'; |
| | | import { MyApp } from './app.component'; |
| | | |
| | | import { StatusBar } from '@ionic-native/status-bar'; |
| | | import { SplashScreen } from '@ionic-native/splash-screen'; |
| | | import { KlCoreModule } from 'kl/core'; |
| | | |
| | | @NgModule({ |
| | | declarations: [ |
| | | MyApp |
| | | ], |
| | | imports: [ |
| | | BrowserModule, |
| | | HttpModule, |
| | | IonicModule.forRoot(MyApp, { |
| | | backButtonText: '', |
| | | tabsHideOnSubPages: true, |
| | | model: 'ios' |
| | | }), |
| | | KlCoreModule |
| | | ], |
| | | bootstrap: [IonicApp], |
| | | entryComponents: [ |
| | | MyApp |
| | | ], |
| | | providers: [ |
| | | StatusBar, |
| | | SplashScreen, |
| | | { provide: ErrorHandler, useClass: IonicErrorHandler } |
| | | ] |
| | | }) |
| | | export class AppModule { } |
New file |
| | |
| | | // http://ionicframework.com/docs/theming/ |
| | | |
| | | |
| | | // App Global Sass |
| | | // -------------------------------------------------- |
| | | // Put style rules here that you want to apply globally. These |
| | | // styles are for the entire app and not just one component. |
| | | // Additionally, this file can be also used as an entry point |
| | | // to import other Sass files to be included in the output CSS. |
| | | // |
| | | // Shared Sass variables, which can be used to adjust Ionic's |
| | | // default Sass variables, belong in "theme/variables.scss". |
| | | // |
| | | // To declare rules for a specific mode, create a child rule |
| | | // for the .md, .ios, or .wp mode classes. The mode class is |
| | | // automatically applied to the <body> element in the app. |
| | | |
| | | // 1. Wechat |
| | | // -------------------------------------------------- |
| | | .wechat{ |
| | | ion-header{ |
| | | display: none !important; |
| | | } |
| | | |
| | | ion-content{ |
| | | .fixed-content{ |
| | | margin-top: 0 !important; |
| | | } |
| | | |
| | | .scroll-content{ |
| | | margin-top: 0 !important; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; |
| | | |
| | | import { AppModule } from './app.module'; |
| | | |
| | | platformBrowserDynamic().bootstrapModule(AppModule); |
New file |
| | |
| | | <!DOCTYPE html> |
| | | <html lang="en" dir="ltr"> |
| | | |
| | | <head> |
| | | <meta charset="UTF-8"> |
| | | <title>Ionic App</title> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> |
| | | <meta name="format-detection" content="telephone=no"> |
| | | <meta name="msapplication-tap-highlight" content="no"> |
| | | |
| | | <link rel="icon" type="image/x-icon" href="assets/icon/favicon.ico"> |
| | | <link rel="manifest" href="manifest.json"> |
| | | <meta name="theme-color" content="#4e8ef7"> |
| | | |
| | | <!-- cordova.js required for cordova apps --> |
| | | <script src="cordova.js"></script> |
| | | |
| | | <!-- un-comment this code to enable service worker |
| | | <script> |
| | | if ('serviceWorker' in navigator) { |
| | | navigator.serviceWorker.register('service-worker.js') |
| | | .then(() => console.log('service worker installed')) |
| | | .catch(err => console.error('Error', err)); |
| | | } |
| | | </script>--> |
| | | |
| | | <link href="build/main.css" rel="stylesheet"> |
| | | |
| | | </head> |
| | | |
| | | <body> |
| | | |
| | | <!-- Ionic's root component and where the app will load --> |
| | | <ion-app></ion-app> |
| | | |
| | | <script> |
| | | var ua = navigator.userAgent.toLowerCase(); |
| | | if (/micromessenger/.test(ua)) { |
| | | document.body.classList.add('wechat'); |
| | | } |
| | | </script> |
| | | |
| | | <!-- The polyfills js is generated during the build process --> |
| | | <script src="build/polyfills.js"></script> |
| | | |
| | | <!-- The vendor js is generated during the build process |
| | | It contains all of the dependencies in node_modules --> |
| | | <script src="build/vendor.js"></script> |
| | | |
| | | <!-- The main bundle js is generated during the build process --> |
| | | <script src="build/main.js"></script> |
| | | |
| | | </body> |
| | | |
| | | </html> |
New file |
| | |
| | | export const Config = { |
| | | environment: 'dev', |
| | | host: '/' |
| | | }; |
New file |
| | |
| | | export const Config = { |
| | | environment: 'dev', |
| | | host: '/' |
| | | }; |
New file |
| | |
| | | export * from './config'; |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | import { IonicStorageModule } from '@ionic/storage'; |
| | | import { HttpClient } from './services/httpclient'; |
| | | import { Logger } from './services/logger'; |
| | | import { LoadingService } from './services/loading.service'; |
| | | import { MessageBox } from './services/messagebox'; |
| | | import { PlatformService } from './services/platform.service'; |
| | | import { AuthService } from './services/auth.service'; |
| | | import './rxjs-operators'; |
| | | |
| | | |
| | | @NgModule({ |
| | | imports: [ |
| | | IonicStorageModule.forRoot({ name: '_xg', driverOrder: ['sqlite', 'localstorage', 'websql', 'indexeddb'] }) |
| | | ], |
| | | exports: [], |
| | | declarations: [], |
| | | providers: [ |
| | | Logger, |
| | | LoadingService, |
| | | HttpClient, |
| | | MessageBox, |
| | | PlatformService, |
| | | AuthService |
| | | ] |
| | | }) |
| | | export class KlCoreModule { } |
New file |
| | |
| | | export * from './core.module'; |
| | | export * from './services/logger'; |
| | | export * from './services/loading.service'; |
| | | export * from './services/httpclient'; |
| | | export * from './services/messagebox'; |
| | | export * from './services/platform.service'; |
| | | export * from './services/auth.service'; |
New file |
| | |
| | | // import 'rxjs/Rx'; // adds ALL RxJS statics & operators to Observable |
| | | |
| | | // See node_module/rxjs/Rxjs.js |
| | | // Import just the rxjs statics and operators needed for THIS app. |
| | | |
| | | // Statics |
| | | import 'rxjs/add/observable/throw'; |
| | | |
| | | // Operators |
| | | import 'rxjs/add/operator/catch'; |
| | | import 'rxjs/add/operator/debounceTime'; |
| | | import 'rxjs/add/operator/distinctUntilChanged'; |
| | | import 'rxjs/add/operator/map'; |
| | | import 'rxjs/add/operator/switchMap'; |
| | | import 'rxjs/add/operator/toPromise'; |
| | | import 'rxjs/add/operator/finally'; |
| | | import 'rxjs/add/observable/of'; |
New file |
| | |
| | | import { Injectable } from '@angular/core'; |
| | | import { Observable } from 'rxjs/Observable'; |
| | | import { Storage } from '@ionic/storage'; |
| | | import { HttpClient } from './httpclient'; |
| | | import { User } from 'kl/model'; |
| | | import { Subject } from 'rxjs/Subject'; |
| | | |
| | | @Injectable() |
| | | export class AuthService { |
| | | |
| | | // TODO 路由守卫 |
| | | |
| | | private _user: User; |
| | | |
| | | constructor(private http: HttpClient, private storage: Storage) { } |
| | | |
| | | } |
New file |
| | |
| | | import { Injectable } from '@angular/core'; |
| | | import { Http, Headers, Response, Request, RequestMethod, RequestOptions } from '@angular/http'; |
| | | import { Observable } from 'rxjs/Observable'; |
| | | import * as moment from 'moment'; |
| | | import { LoadingService } from './loading.service'; |
| | | import { ApiResult } from 'kl/model'; |
| | | |
| | | @Injectable() |
| | | export class HttpClient { |
| | | |
| | | constructor(private http: Http, private loading: LoadingService) { } |
| | | |
| | | get(api: string, fun: Function) { |
| | | this.getResponse(this.http.get(api), fun); |
| | | } |
| | | |
| | | post (api: string, params: Object, fun: Function) { |
| | | this.getResponse(this.http.post(api, params), fun); |
| | | } |
| | | |
| | | xhrPost(api, data, fun) { |
| | | let xhr = new XMLHttpRequest(); |
| | | xhr.open('POST', api, false); |
| | | xhr.onload = () => fun(JSON.parse(xhr.response)); |
| | | xhr.setRequestHeader('Content-Type', 'application/json'); |
| | | xhr.send(JSON.stringify(data) ); |
| | | } |
| | | |
| | | private getResponse(res: Observable<Response>, fun) { |
| | | res.subscribe(response => { |
| | | let json = response.json(); |
| | | fun(json); |
| | | }, error => {} |
| | | ); |
| | | } |
| | | |
| | | request<T>(url: string, method: RequestMethod, body?: any, showLoading?: boolean): Observable<ApiResult<T>> { |
| | | let headers = new Headers(); |
| | | |
| | | let options = new RequestOptions(); |
| | | options.headers = headers; |
| | | options.url = url; |
| | | options.method = method; |
| | | options.body = body; |
| | | options.withCredentials = true; |
| | | |
| | | let request = new Request(options); |
| | | |
| | | if (showLoading !== false) this.loading.show(); |
| | | |
| | | return this.http.request(request) |
| | | .finally(() => { |
| | | if (showLoading !== false) this.loading.hide(); |
| | | }).map(r => r.json() as T) |
| | | .catch(x => this.handleError(x)); |
| | | } |
| | | |
| | | /** |
| | | * 将字典转为QueryString |
| | | */ |
| | | private _formatUrl(params?: { [key: string]: string }): string { |
| | | if (!params) return ''; |
| | | |
| | | let fegment = []; |
| | | for (let k in params) { |
| | | let v: any = params[k]; |
| | | if (v instanceof Date) { |
| | | v = moment(v).format('YYYY-MM-DD HH:mm:SS'); |
| | | } |
| | | fegment.push(`${k}=${v}`); |
| | | } |
| | | return '?' + fegment.join('&'); |
| | | } |
| | | |
| | | /** |
| | | * 通用异常处理 |
| | | */ |
| | | private handleError(error: Response | any) { |
| | | let errMsg: string; |
| | | if (error instanceof Response) { |
| | | const body = error.json() || ''; |
| | | const err = body.error || JSON.stringify(body); |
| | | errMsg = `${error.status} - ${error.statusText || ''} ${err}`; |
| | | } else { |
| | | errMsg = error ? error.toString() : '服务器发生异常,请稍后再试'; |
| | | } |
| | | return Observable.throw(errMsg); |
| | | } |
| | | } |
New file |
| | |
| | | import { Injectable } from '@angular/core'; |
| | | import { LoadingController, Loading } from 'ionic-angular'; |
| | | |
| | | @Injectable() |
| | | export class LoadingService { |
| | | private loader: Loading; |
| | | private isShow = false; |
| | | |
| | | constructor(public loadingCtrl: LoadingController) { |
| | | } |
| | | |
| | | show() { |
| | | if (this.isShow) return; |
| | | this.loader = this.loadingCtrl.create({ |
| | | content: '请稍等...' |
| | | }); |
| | | this.isShow = true; |
| | | this.loader.present(); |
| | | } |
| | | |
| | | hide() { |
| | | if (!this.isShow) return; |
| | | this.isShow = false; |
| | | this.loader.dismiss(); |
| | | } |
| | | } |
New file |
| | |
| | | import { Injectable } from '@angular/core'; |
| | | import { ToastController } from 'ionic-angular'; |
| | | |
| | | @Injectable() |
| | | export class Logger { |
| | | |
| | | constructor(private toastCtrl: ToastController) { } |
| | | |
| | | /** |
| | | * 显示通知 |
| | | * @param msg 显示的内容 |
| | | * @param extro 将被保存到日志 |
| | | */ |
| | | info(msg: string, extro?: any) { |
| | | this._show(msg, 'secondary'); |
| | | this.save(extro); |
| | | } |
| | | |
| | | /** |
| | | * 显示警告 |
| | | * @param msg 警告的内容 |
| | | * @param extro 将被保存到日志 |
| | | */ |
| | | warn(msg: string, extro?: any) { |
| | | this._show(msg, 'danger'); |
| | | this.save(extro); |
| | | } |
| | | |
| | | /** |
| | | * 显示错误 |
| | | * @param msg 错误的内容 |
| | | * @param extro 将被保存到日志 |
| | | */ |
| | | error(msg: string, extro?: any) { |
| | | this._show(msg, 'danger'); |
| | | this.save(extro); |
| | | } |
| | | |
| | | /** |
| | | * 保存日志 |
| | | * @param msg 错误的内容 |
| | | * @param extro 将被保存为本地日志 |
| | | */ |
| | | save(extro?: any) { |
| | | if (!extro) return; |
| | | console.log(JSON.stringify(extro)); |
| | | } |
| | | |
| | | private _show(msg: string, css: string) { |
| | | let toast = this.toastCtrl.create({ |
| | | message: msg, |
| | | duration: 3000, |
| | | cssClass: css |
| | | }); |
| | | |
| | | toast.present(); |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | import { Injectable } from '@angular/core'; |
| | | import { AlertController, AlertOptions, ToastController } from 'ionic-angular'; |
| | | |
| | | @Injectable() |
| | | export class MessageBox { |
| | | |
| | | constructor(private alertCtrl: AlertController, private toastCtrl: ToastController) { } |
| | | |
| | | /** |
| | | * Toast提示框 |
| | | */ |
| | | toast(msg: string, css: string = '') { |
| | | let toast = this.toastCtrl.create({ |
| | | message: msg, |
| | | duration: 3000, |
| | | cssClass: css |
| | | }); |
| | | |
| | | toast.present(); |
| | | } |
| | | |
| | | /** 提示框 */ |
| | | alert(msg: string) { |
| | | let options: AlertOptions = { |
| | | title: '', |
| | | subTitle: msg, |
| | | buttons: [ |
| | | { |
| | | text: '', |
| | | }, |
| | | { |
| | | text: '确定', |
| | | } |
| | | ] |
| | | }; |
| | | this._present(options); |
| | | } |
| | | |
| | | /** |
| | | * 确认框 |
| | | */ |
| | | confirm( |
| | | msg: string, |
| | | onOk: () => void, |
| | | onCancel = () => { }, |
| | | okText = '确定', |
| | | cancelText = '' |
| | | ) { |
| | | let options: AlertOptions = { |
| | | title: '', |
| | | message: msg, |
| | | buttons: [ |
| | | { |
| | | text: cancelText, |
| | | role: 'cancel', |
| | | handler: onCancel |
| | | }, |
| | | { |
| | | text: okText, |
| | | role: 'ok', |
| | | handler: onOk |
| | | } |
| | | ] |
| | | }; |
| | | this._present(options); |
| | | } |
| | | |
| | | /** |
| | | * 输入框 |
| | | */ |
| | | prompt( |
| | | msg: string, |
| | | inputName: string, |
| | | inputPlaceholer: string, |
| | | onOk: (data: any) => void, |
| | | onCancel = (data: any) => { }, |
| | | okText = '确定', |
| | | cancelText = '' |
| | | ) { |
| | | this._present({ |
| | | title: '请输入', |
| | | subTitle: msg, |
| | | inputs: [ |
| | | { |
| | | name: inputName, |
| | | placeholder: inputPlaceholer |
| | | } |
| | | ], |
| | | buttons: [ |
| | | { |
| | | text: cancelText, |
| | | role: 'cancel', |
| | | handler: onCancel |
| | | }, |
| | | { |
| | | text: okText, |
| | | role: 'ok', |
| | | handler: onOk |
| | | } |
| | | ] |
| | | }); |
| | | } |
| | | |
| | | private _present(options: AlertOptions) { |
| | | options.cssClass = 'messagebox'; |
| | | let alert = this.alertCtrl.create(options); |
| | | alert.present(); |
| | | } |
| | | } |
New file |
| | |
| | | import { Injectable } from '@angular/core'; |
| | | import { Platform, ToastController, Nav, Tab } from 'ionic-angular'; |
| | | import { TabsPage } from '../../../pages/tabs/tabs'; |
| | | |
| | | declare let WeixinJSBridge: any; |
| | | |
| | | @Injectable() |
| | | export class PlatformService { |
| | | /** |
| | | * 用于判断返回键是否触发 |
| | | * |
| | | * @private |
| | | * @type {boolean} |
| | | * @memberOf PlatformService |
| | | */ |
| | | private _backButtonPressed: boolean = false; |
| | | |
| | | private _rootNav: Nav; |
| | | |
| | | /** |
| | | * 在首页加载完成后,设置根导航组件 |
| | | * |
| | | * @memberOf PlatformService |
| | | */ |
| | | public set rootNav(nav: Nav) { |
| | | this._rootNav = nav; |
| | | } |
| | | |
| | | constructor( |
| | | private platform: Platform, |
| | | private toastCtrl: ToastController |
| | | ) { } |
| | | |
| | | /** |
| | | * 注册返回键事件 |
| | | * |
| | | * @memberOf PlatformService |
| | | */ |
| | | registerBackButton() { |
| | | if (this.platform.is('android')) { |
| | | this._registerAndroidExit(); |
| | | } else if (this._isWechat()) { |
| | | // 注册返回事件 |
| | | this._registerBrowserBack(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据UserAgent判断是否微信浏览器 |
| | | * |
| | | * |
| | | * @memberOf PlatformService |
| | | */ |
| | | private _isWechat() { |
| | | if (this.__isWechat === undefined) { |
| | | let ua = navigator.userAgent.toLowerCase(); |
| | | this.__isWechat = /micromessenger/.test(ua); |
| | | } |
| | | return this.__isWechat; |
| | | } |
| | | private __isWechat: boolean = undefined; |
| | | |
| | | /** |
| | | * 为安卓注册双击返回退出app |
| | | * |
| | | * @private |
| | | * |
| | | * @memberOf MyApp |
| | | */ |
| | | private _registerAndroidExit() { |
| | | this.platform.registerBackButtonAction((): any => this._onBackButtonClicked, 101); |
| | | } |
| | | |
| | | /** |
| | | * 注册浏览器返回事件 |
| | | */ |
| | | private _registerBrowserBack() { |
| | | window.addEventListener('popstate', () => { |
| | | this._onBackButtonClicked(); |
| | | }, false); |
| | | } |
| | | |
| | | /** |
| | | * 双击退出提示框,这里使用Ionic2的ToastController |
| | | * |
| | | * @private |
| | | * |
| | | * @memberOf MyApp |
| | | */ |
| | | private _showExit() { |
| | | if (this._backButtonPressed) { |
| | | // 当触发标志为true时,即2秒内双击返回按键则退出APP |
| | | if (this._isWechat()) { |
| | | WeixinJSBridge.call('closeWindow'); |
| | | } else { |
| | | this.platform.exitApp(); |
| | | } |
| | | } else { |
| | | let toast = this.toastCtrl.create({ |
| | | message: '再按一次退出应用', |
| | | duration: 2000, |
| | | position: 'bottom' |
| | | }); |
| | | toast.present(); |
| | | this._backButtonPressed = true; |
| | | // 2秒内没有再次点击返回则将触发标志标记为false |
| | | setTimeout(() => { |
| | | this._backButtonPressed = false; |
| | | }, 2000); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 响应返回键点击事件 |
| | | * |
| | | * @private |
| | | * |
| | | * @memberOf MyApp |
| | | */ |
| | | private _onBackButtonClicked() { |
| | | if (this._isWechat()) { |
| | | if (this._pop) { // 阻止pop()方法引用多次返回 |
| | | this._pop = false; |
| | | return; |
| | | } |
| | | } |
| | | let activeVC = this._rootNav.getActive(); |
| | | let page = activeVC.instance; |
| | | if (!(page instanceof TabsPage)) { |
| | | if (!this._rootNav.canGoBack()) { |
| | | // 当前页面为tabs,退出APP |
| | | return this._showExit(); |
| | | } |
| | | // 当前页面为tabs的子页面,正常返回 |
| | | return this._rootNav.pop(); |
| | | } |
| | | // 获取主Tab组件 |
| | | let tabs = page.tabs; |
| | | let activeNav = tabs.getSelected(); |
| | | if (!this._canGoBack(activeNav)) { |
| | | // 当前页面为tab栏,退出APP |
| | | return this._showExit(); |
| | | } |
| | | // 当前页面为tab栏的子页面,正常返回 |
| | | return activeNav.pop(); |
| | | } |
| | | |
| | | // 解决微信模式下,根页面在页面栈中出现两次而无法返回的问题 |
| | | private _canGoBack(tab: Tab): boolean { |
| | | if (!this._isWechat()) { |
| | | return tab.canGoBack(); |
| | | } |
| | | |
| | | const active = tab.getActive(); |
| | | if (!active) return false; |
| | | const activeNav = active.getNav(); |
| | | if (!activeNav) return false; |
| | | const previous = tab.getPrevious(); |
| | | if (!previous) return false; |
| | | if (previous.id === active.id) return false; |
| | | return true; |
| | | } |
| | | |
| | | private _pop = false; |
| | | pop(nav) { |
| | | this._pop = true; |
| | | nav.pop(); |
| | | } |
| | | } |
New file |
| | |
| | | export class ApiResult<T> { |
| | | Code: number; |
| | | Message: string; |
| | | Data: T; |
| | | } |
New file |
| | |
| | | export * from './api.result'; |
| | | export * from './user'; |
New file |
| | |
| | | export class User { |
| | | Id: number; |
| | | Name: string; |
| | | Password: string; |
| | | } |
New file |
| | |
| | | import { Directive, Input, Output, HostListener, EventEmitter } from '@angular/core'; |
| | | import { Subject } from 'rxjs/Subject'; |
| | | import { Observable } from 'rxjs/Observable'; |
| | | import { Camera, CameraOptions } from '@ionic-native/camera'; |
| | | import { ActionSheetController } from 'ionic-angular'; |
| | | /** |
| | | * 拍照或者从相册中选取一张图片 |
| | | * 用法:<span [camera]="options" (completed)="onCameraCompleted($event)"><span> |
| | | * |
| | | * 问题: |
| | | * 1. 安卓机上,completed的绑定方法里设置页面的img的src绑定属性无效,暂时使用js赋值的方式解决 |
| | | * onCameraCompleted(fileUrl:string) { |
| | | * (document.getElementById('img_test') as any).src=fileUrl; |
| | | * } |
| | | */ |
| | | @Directive({ selector: '[camera]' }) |
| | | export class CameraDirective { |
| | | |
| | | private _default: CameraOptions; |
| | | |
| | | private _options: CameraOptions; |
| | | |
| | | constructor( |
| | | private actionSheetCtrl: ActionSheetController, |
| | | private cameraPlugin: Camera |
| | | ) { |
| | | this._default = { |
| | | quality: 100, |
| | | destinationType: this.cameraPlugin.DestinationType.FILE_URI, |
| | | sourceType: this.cameraPlugin.PictureSourceType.CAMERA, |
| | | allowEdit: true, |
| | | targetWidth: 100, |
| | | targetHeight: 100, |
| | | mediaType: this.cameraPlugin.MediaType.PICTURE, |
| | | correctOrientation: true, |
| | | saveToPhotoAlbum: false, |
| | | cameraDirection: this.cameraPlugin.Direction.BACK |
| | | }; |
| | | } |
| | | |
| | | @Output() completed = new EventEmitter<string>(); |
| | | |
| | | @Input() |
| | | set camera(options: CameraOptions) { |
| | | this._options = this._extend(options, this._default); |
| | | } |
| | | |
| | | @HostListener('click') |
| | | onClick() { |
| | | this._presentActionSheet() |
| | | .subscribe( |
| | | type => { |
| | | this._options.sourceType = type; |
| | | this.cameraPlugin.getPicture(this._options).then((imageData) => { |
| | | this.completed.emit(imageData); |
| | | }, (err) => { |
| | | console.error('获取图片失败:' + JSON.stringify(err)); |
| | | }); |
| | | }, |
| | | error => { |
| | | console.error('选择获取头像方式失败:' + error); |
| | | }); |
| | | } |
| | | |
| | | private _extend<T>(left: T, right: T): T { |
| | | if (!(left && left instanceof Object)) return right; |
| | | |
| | | if (right && right instanceof Object) { |
| | | for (let k in right) { |
| | | if (right[k] && right[k] !== left[k]) { |
| | | left[k] = right[k]; |
| | | } |
| | | } |
| | | } |
| | | return left; |
| | | } |
| | | |
| | | private _presentActionSheet(): Observable<number> { |
| | | let sub = new Subject<number>(); |
| | | let actionSheet = this.actionSheetCtrl.create({ |
| | | title: '选择头像', |
| | | buttons: [ |
| | | { |
| | | text: '拍照', |
| | | role: '1', |
| | | handler: () => sub.next(1) |
| | | }, |
| | | { |
| | | text: '相册', |
| | | role: '0', |
| | | handler: () => sub.next(0) |
| | | }, |
| | | { |
| | | text: '取消', |
| | | role: 'cancel', |
| | | handler: () => sub.error(-1) |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | actionSheet.present(); |
| | | return sub.asObservable(); |
| | | } |
| | | } |
New file |
| | |
| | | export * from './shared.module'; |
| | | export * from './pipes/localdate.pipe'; |
New file |
| | |
| | | import { Pipe, PipeTransform } from '@angular/core'; |
| | | import { DatePipe } from '@angular/common'; |
| | | |
| | | /** |
| | | * 1. 将UTC时间,改为本地时间:2017-1-1T12:01 |
| | | * 2. 将json时间,改为本地时间:‘/Date(1472608668000)/’ |
| | | */ |
| | | @Pipe({ |
| | | name: 'date' |
| | | }) |
| | | |
| | | export class LocalDatePipe implements PipeTransform { |
| | | constructor(private date: DatePipe) { } |
| | | transform(value: any, pattern?: string): string { |
| | | if (value instanceof Date) { |
| | | return this.date.transform(value, pattern); |
| | | } |
| | | if (value.indexOf('T') >= 0) { |
| | | return this.date.transform(value.replace('T', ' '), pattern); |
| | | } |
| | | let myRex = /^\/Date\(\d*\)\/$/; |
| | | if (myRex.test(value)) { |
| | | value = new Date(parseInt(value.replace(/^\/Date\(/, '').replace(/\)\/$/, ''), 10)); |
| | | } |
| | | return this.date.transform(value, pattern); |
| | | } |
| | | } |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | import { CameraDirective } from './directives/camera.directive'; |
| | | import { LocalDatePipe } from './pipes/localdate.pipe'; |
| | | import { DatePipe } from '@angular/common'; |
| | | |
| | | const _PROVIDDERS = [ |
| | | DatePipe, |
| | | LocalDatePipe |
| | | ]; |
| | | |
| | | const _DECLARATIONS = [ |
| | | CameraDirective, |
| | | LocalDatePipe |
| | | ]; |
| | | |
| | | @NgModule({ |
| | | imports: [], |
| | | exports: [ |
| | | ..._DECLARATIONS |
| | | ], |
| | | declarations: [ |
| | | ..._DECLARATIONS |
| | | ], |
| | | providers: [ |
| | | ..._PROVIDDERS |
| | | ], |
| | | }) |
| | | export class KlSharedModule { } |
New file |
| | |
| | | { |
| | | "name": "Ionic", |
| | | "short_name": "Ionic", |
| | | "start_url": "index.html", |
| | | "display": "standalone", |
| | | "icons": [{ |
| | | "src": "assets/imgs/logo.png", |
| | | "sizes": "512x512", |
| | | "type": "image/png" |
| | | }], |
| | | "background_color": "#4e8ef7", |
| | | "theme_color": "#4e8ef7" |
| | | } |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | |
| | | import { LoginService } from './services'; |
| | | |
| | | @NgModule({ |
| | | imports: [], |
| | | exports: [], |
| | | declarations: [], |
| | | providers: [LoginService], |
| | | }) |
| | | export class AccessModule { } |
New file |
| | |
| | | <!-- |
| | | Generated template for the ForgotpwdPage page. |
| | | |
| | | See http://ionicframework.com/docs/components/#navigation for more info on |
| | | Ionic pages and navigation. |
| | | --> |
| | | <ion-header> |
| | | |
| | | <ion-navbar> |
| | | <ion-title>forgotpwd</ion-title> |
| | | </ion-navbar> |
| | | |
| | | </ion-header> |
| | | |
| | | |
| | | <ion-content padding> |
| | | |
| | | </ion-content> |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | import { IonicPageModule } from 'ionic-angular'; |
| | | import { ForgotpwdPage } from './forgotpwd'; |
| | | |
| | | @NgModule({ |
| | | declarations: [ |
| | | ForgotpwdPage, |
| | | ], |
| | | imports: [ |
| | | IonicPageModule.forChild(ForgotpwdPage), |
| | | ], |
| | | }) |
| | | export class ForgotpwdPageModule {} |
New file |
| | |
| | | page-forgotpwd { |
| | | |
| | | } |
New file |
| | |
| | | import { Component } from '@angular/core'; |
| | | import { IonicPage, NavController, NavParams } from 'ionic-angular'; |
| | | |
| | | /** |
| | | * Generated class for the ForgotpwdPage page. |
| | | * |
| | | * See http://ionicframework.com/docs/components/#navigation for more info |
| | | * on Ionic pages and navigation. |
| | | */ |
| | | |
| | | @IonicPage({ |
| | | name: 'access-forgorpwd' |
| | | }) |
| | | @Component({ |
| | | selector: 'page-forgotpwd', |
| | | templateUrl: 'forgotpwd.html', |
| | | }) |
| | | export class ForgotpwdPage { |
| | | |
| | | constructor(public navCtrl: NavController, public navParams: NavParams) { |
| | | } |
| | | |
| | | ionViewDidLoad() { |
| | | console.log('ionViewDidLoad ForgotpwdPage'); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | <ion-header> |
| | | |
| | | <ion-navbar> |
| | | <ion-title>login</ion-title> |
| | | </ion-navbar> |
| | | |
| | | </ion-header> |
| | | |
| | | |
| | | <ion-content padding> |
| | | <button ion-button (click)="register()">Register</button> |
| | | </ion-content> |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | import { IonicPageModule } from 'ionic-angular'; |
| | | import { LoginPage } from './login'; |
| | | import { AccessModule } from '../../access.module'; |
| | | |
| | | @NgModule({ |
| | | declarations: [ |
| | | LoginPage, |
| | | ], |
| | | imports: [ |
| | | AccessModule, |
| | | IonicPageModule.forChild(LoginPage), |
| | | ], |
| | | }) |
| | | export class LoginPageModule { } |
New file |
| | |
| | | import { Component } from '@angular/core'; |
| | | import { IonicPage, NavController } from 'ionic-angular'; |
| | | |
| | | import { LoginService } from '../../services'; |
| | | |
| | | @IonicPage({ |
| | | name: 'access-login' |
| | | }) |
| | | @Component({ |
| | | selector: 'page-login', |
| | | templateUrl: 'login.html', |
| | | }) |
| | | export class LoginPage { |
| | | |
| | | constructor( |
| | | public navCtrl: NavController, |
| | | private service: LoginService) { |
| | | } |
| | | |
| | | ionViewDidLoad() { |
| | | this.service.login(); |
| | | } |
| | | |
| | | register() { |
| | | this.navCtrl.push('access-register'); |
| | | } |
| | | } |
New file |
| | |
| | | <ion-header> |
| | | |
| | | <ion-navbar> |
| | | <ion-title>register</ion-title> |
| | | </ion-navbar> |
| | | |
| | | </ion-header> |
| | | |
| | | |
| | | <ion-content padding> |
| | | <button ion-button block (click)="back()">Back</button> |
| | | </ion-content> |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | import { IonicPageModule } from 'ionic-angular'; |
| | | import { RegisterPage } from './register'; |
| | | import { AccessModule } from '../../access.module'; |
| | | |
| | | @NgModule({ |
| | | declarations: [ |
| | | RegisterPage, |
| | | ], |
| | | imports: [ |
| | | AccessModule, |
| | | IonicPageModule.forChild(RegisterPage), |
| | | ], |
| | | }) |
| | | export class RegisterPageModule { } |
New file |
| | |
| | | page-register { |
| | | |
| | | } |
New file |
| | |
| | | import { Component } from '@angular/core'; |
| | | import { IonicPage, NavController, NavParams } from 'ionic-angular'; |
| | | |
| | | import { LoginService } from '../../services'; |
| | | |
| | | @IonicPage({ |
| | | name: 'access-register' |
| | | }) |
| | | @Component({ |
| | | selector: 'page-register', |
| | | templateUrl: 'register.html', |
| | | }) |
| | | export class RegisterPage { |
| | | |
| | | constructor(public navCtrl: NavController, public navParams: NavParams, private service: LoginService) { |
| | | } |
| | | |
| | | ionViewDidLoad() { |
| | | this.service.register(); |
| | | } |
| | | |
| | | back() { |
| | | this.navCtrl.pop(); |
| | | } |
| | | } |
New file |
| | |
| | | export * from './login.service'; |
New file |
| | |
| | | import { Injectable } from '@angular/core'; |
| | | |
| | | @Injectable() |
| | | export class LoginService { |
| | | |
| | | constructor() { } |
| | | |
| | | login() { |
| | | console.log('login for demo'); |
| | | } |
| | | |
| | | register() { |
| | | console.log('register for demo'); |
| | | } |
| | | } |
New file |
| | |
| | | <ion-header> |
| | | |
| | | <ion-navbar> |
| | | <ion-title>about</ion-title> |
| | | </ion-navbar> |
| | | |
| | | </ion-header> |
| | | |
| | | |
| | | <ion-content padding> |
| | | |
| | | </ion-content> |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | import { IonicPageModule } from 'ionic-angular'; |
| | | import { AboutPage } from './about'; |
| | | |
| | | @NgModule({ |
| | | declarations: [ |
| | | AboutPage, |
| | | ], |
| | | imports: [ |
| | | IonicPageModule.forChild(AboutPage), |
| | | ], |
| | | }) |
| | | export class AboutPageModule {} |
New file |
| | |
| | | import { Component } from '@angular/core'; |
| | | import { IonicPage, NavController, NavParams } from 'ionic-angular'; |
| | | |
| | | @IonicPage({ |
| | | name: 'about' |
| | | }) |
| | | @Component({ |
| | | selector: 'page-about', |
| | | templateUrl: 'about.html', |
| | | }) |
| | | export class AboutPage { |
| | | |
| | | constructor(public navCtrl: NavController, public navParams: NavParams) { |
| | | } |
| | | |
| | | ionViewDidLoad() { |
| | | console.log('ionViewDidLoad AboutPage'); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | <ion-header> |
| | | |
| | | <ion-navbar> |
| | | <ion-title>contact</ion-title> |
| | | </ion-navbar> |
| | | |
| | | </ion-header> |
| | | |
| | | |
| | | <ion-content padding> |
| | | |
| | | </ion-content> |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | import { IonicPageModule } from 'ionic-angular'; |
| | | import { ContactPage } from './contact'; |
| | | |
| | | @NgModule({ |
| | | declarations: [ |
| | | ContactPage, |
| | | ], |
| | | imports: [ |
| | | IonicPageModule.forChild(ContactPage), |
| | | ], |
| | | }) |
| | | export class ContactPageModule {} |
New file |
| | |
| | | page-contact { |
| | | |
| | | } |
New file |
| | |
| | | import { Component } from '@angular/core'; |
| | | import { IonicPage, NavController, NavParams } from 'ionic-angular'; |
| | | |
| | | @IonicPage({ |
| | | name: 'contact' |
| | | }) |
| | | @Component({ |
| | | selector: 'page-contact', |
| | | templateUrl: 'contact.html', |
| | | }) |
| | | export class ContactPage { |
| | | |
| | | constructor(public navCtrl: NavController, public navParams: NavParams) { |
| | | } |
| | | |
| | | ionViewDidLoad() { |
| | | console.log('ionViewDidLoad ContactPage'); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | <ion-header> |
| | | |
| | | <ion-navbar> |
| | | <ion-title>home</ion-title> |
| | | </ion-navbar> |
| | | |
| | | </ion-header> |
| | | |
| | | |
| | | <ion-content padding> |
| | | <button ion-button (click)="go()">Login</button> |
| | | </ion-content> |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | import { IonicPageModule } from 'ionic-angular'; |
| | | import { HomePage } from './home'; |
| | | |
| | | @NgModule({ |
| | | declarations: [ |
| | | HomePage, |
| | | ], |
| | | imports: [ |
| | | IonicPageModule.forChild(HomePage), |
| | | ], |
| | | }) |
| | | export class HomePageModule {} |
New file |
| | |
| | | import { Component } from '@angular/core'; |
| | | import { IonicPage, NavController, NavParams } from 'ionic-angular'; |
| | | |
| | | @IonicPage({ |
| | | name: 'home' |
| | | }) |
| | | @Component({ |
| | | selector: 'page-home', |
| | | templateUrl: 'home.html', |
| | | }) |
| | | export class HomePage { |
| | | |
| | | constructor(public navCtrl: NavController, public navParams: NavParams) { |
| | | } |
| | | |
| | | ionViewDidLoad() { |
| | | console.log('ionViewDidLoad HomePage'); |
| | | } |
| | | |
| | | go() { |
| | | this.navCtrl.push('access-login'); |
| | | } |
| | | } |
New file |
| | |
| | | <ion-tabs #mainTabs> |
| | | <ion-tab [root]="tab1Root" tabTitle="Home" tabIcon="home"></ion-tab> |
| | | <ion-tab [root]="tab2Root" tabTitle="About" tabIcon="information-circle"></ion-tab> |
| | | <ion-tab [root]="tab3Root" tabTitle="Contact" tabIcon="contacts"></ion-tab> |
| | | </ion-tabs> |
New file |
| | |
| | | import { NgModule } from '@angular/core'; |
| | | import { IonicPageModule } from 'ionic-angular'; |
| | | import { TabsPage } from './tabs'; |
| | | |
| | | @NgModule({ |
| | | declarations: [ |
| | | TabsPage, |
| | | ], |
| | | imports: [ |
| | | IonicPageModule.forChild(TabsPage), |
| | | ], |
| | | }) |
| | | export class TabsPageModule { } |
New file |
| | |
| | | import { Component, ViewChild } from '@angular/core'; |
| | | import { Tabs, IonicPage } from 'ionic-angular'; |
| | | |
| | | @IonicPage({ |
| | | name: 'maintabs' |
| | | }) |
| | | @Component({ |
| | | templateUrl: 'tabs.html' |
| | | }) |
| | | export class TabsPage { |
| | | |
| | | tab1Root = 'home'; |
| | | tab2Root = 'about'; |
| | | tab3Root = 'contact'; |
| | | |
| | | @ViewChild('mainTabs') tabs: Tabs; |
| | | constructor() { |
| | | |
| | | } |
| | | } |
New file |
| | |
| | | /** |
| | | * Check out https://googlechrome.github.io/sw-toolbox/ for |
| | | * more info on how to use sw-toolbox to custom configure your service worker. |
| | | */ |
| | | |
| | | |
| | | 'use strict'; |
| | | importScripts('./build/sw-toolbox.js'); |
| | | |
| | | self.toolbox.options.cache = { |
| | | name: 'ionic-cache' |
| | | }; |
| | | |
| | | // pre-cache our key assets |
| | | self.toolbox.precache( |
| | | [ |
| | | './build/main.js', |
| | | './build/vendor.js', |
| | | './build/main.css', |
| | | './build/polyfills.js', |
| | | 'index.html', |
| | | 'manifest.json' |
| | | ] |
| | | ); |
| | | |
| | | // dynamically cache any other local assets |
| | | self.toolbox.router.any('/*', self.toolbox.cacheFirst); |
| | | |
| | | // for any other requests go to the network, cache, |
| | | // and then only use that cached resource if your user goes offline |
| | | self.toolbox.router.default = self.toolbox.networkFirst; |
New file |
| | |
| | | // Ionic Variables and Theming. For more info, please see: |
| | | // http://ionicframework.com/docs/theming/ |
| | | |
| | | // Font path is used to include ionicons, |
| | | // roboto, and noto sans fonts |
| | | $font-path: "../assets/fonts"; |
| | | |
| | | |
| | | // The app direction is used to include |
| | | // rtl styles in your app. For more info, please see: |
| | | // http://ionicframework.com/docs/theming/rtl-support/ |
| | | $app-direction: ltr; |
| | | |
| | | |
| | | @import "ionic.globals"; |
| | | |
| | | |
| | | // Shared Variables |
| | | // -------------------------------------------------- |
| | | // To customize the look and feel of this app, you can override |
| | | // the Sass variables found in Ionic's source scss files. |
| | | // To view all the possible Ionic variables, see: |
| | | // http://ionicframework.com/docs/theming/overriding-ionic-variables/ |
| | | |
| | | |
| | | |
| | | |
| | | // Named Color Variables |
| | | // -------------------------------------------------- |
| | | // Named colors makes it easy to reuse colors on various components. |
| | | // It's highly recommended to change the default colors |
| | | // to match your app's branding. Ionic uses a Sass map of |
| | | // colors so you can add, rename and remove colors as needed. |
| | | // The "primary" color is the only required color in the map. |
| | | |
| | | $colors: ( |
| | | primary: #488aff, |
| | | secondary: #32db64, |
| | | danger: #f53d3d, |
| | | light: #f4f4f4, |
| | | dark: #222 |
| | | ); |
| | | |
| | | |
| | | // App iOS Variables |
| | | // -------------------------------------------------- |
| | | // iOS only Sass variables can go here |
| | | |
| | | |
| | | |
| | | |
| | | // App Material Design Variables |
| | | // -------------------------------------------------- |
| | | // Material Design only Sass variables can go here |
| | | |
| | | |
| | | |
| | | |
| | | // App Windows Variables |
| | | // -------------------------------------------------- |
| | | // Windows only Sass variables can go here |
| | | |
| | | |
| | | |
| | | |
| | | // App Theme |
| | | // -------------------------------------------------- |
| | | // Ionic apps can have different themes applied, which can |
| | | // then be future customized. This import comes last |
| | | // so that the above variables are used and Ionic's |
| | | // default are overridden. |
| | | |
| | | @import "ionic.theme.default"; |
| | | |
| | | |
| | | // Ionicons |
| | | // -------------------------------------------------- |
| | | // The premium icon font for Ionic. For more info, please see: |
| | | // http://ionicframework.com/docs/ionicons/ |
| | | |
| | | @import "ionic.ionicons"; |
| | | |
| | | |
| | | // Fonts |
| | | // -------------------------------------------------- |
| | | |
| | | @import "roboto"; |
| | | @import "noto-sans"; |
New file |
| | |
| | | { |
| | | "compilerOptions": { |
| | | "allowSyntheticDefaultImports": true, |
| | | "declaration": false, |
| | | "emitDecoratorMetadata": true, |
| | | "experimentalDecorators": true, |
| | | "lib": [ |
| | | "dom", |
| | | "es2015" |
| | | ], |
| | | "module": "es2015", |
| | | "moduleResolution": "node", |
| | | "sourceMap": true, |
| | | "target": "es5", |
| | | "baseUrl": "./src" |
| | | }, |
| | | "include": [ |
| | | "src/**/*.ts" |
| | | ], |
| | | "exclude": [ |
| | | "node_modules" |
| | | ], |
| | | "compileOnSave": false, |
| | | "atom": { |
| | | "rewriteTsconfig": false |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "extends": "tslint-ionic-rules", |
| | | "rules": { |
| | | "no-duplicate-variable": true, |
| | | "quotemark": [ |
| | | true, |
| | | "single", |
| | | "avoid-escape", |
| | | "avoid-template" |
| | | ], |
| | | "no-unused-variable": [ |
| | | true |
| | | ], |
| | | "ordered-imports": { |
| | | "options": { |
| | | "import-sources-order": "any", |
| | | "named-imports-order": "any" |
| | | } |
| | | } |
| | | }, |
| | | "rulesDirectory": [ |
| | | "node_modules/tslint-eslint-rules/dist/rules" |
| | | ] |
| | | } |