├── src ├── app │ ├── shared │ │ ├── components │ │ │ ├── shop │ │ │ │ ├── list │ │ │ │ │ ├── shop-list.scss │ │ │ │ │ ├── shop-list.ts │ │ │ │ │ └── shop-list.html │ │ │ │ ├── search │ │ │ │ │ ├── shop-search.ts │ │ │ │ │ ├── shop-search.html │ │ │ │ │ └── shop-search.scss │ │ │ │ ├── msite │ │ │ │ │ ├── shop-msite.ts │ │ │ │ │ ├── shop-msite.html │ │ │ │ │ └── shop-msite.scss │ │ │ │ └── evaluate │ │ │ │ │ ├── evaluate.ts │ │ │ │ │ └── evaluate.html │ │ │ ├── index.ts │ │ │ ├── svg │ │ │ │ └── svg.ts │ │ │ ├── login-header │ │ │ │ ├── login-header.html │ │ │ │ ├── login-header.scss │ │ │ │ └── login-header.ts │ │ │ ├── rating-star │ │ │ │ ├── rating-star.ts │ │ │ │ ├── rating-star.scss │ │ │ │ └── rating-star.html │ │ │ ├── loading │ │ │ │ ├── loading.html │ │ │ │ ├── loading.ts │ │ │ │ └── loading.scss │ │ │ ├── back │ │ │ │ ├── back-header.ts │ │ │ │ └── back-icon.ts │ │ │ ├── buy-cart │ │ │ │ ├── buy-cart.html │ │ │ │ ├── buy-cart.scss │ │ │ │ └── buy-cart.ts │ │ │ └── components.module.ts │ │ ├── index.ts │ │ └── shared.module.ts │ ├── class │ │ ├── index.ts │ │ └── userinfo.ts │ ├── core │ │ ├── index.ts │ │ └── core.module.ts │ ├── tabs │ │ ├── tabs.page.scss │ │ ├── tabs.page.ts │ │ ├── tabs.page.html │ │ ├── tabs.module.ts │ │ └── tabs.router.module.ts │ ├── config │ │ └── env.ts │ ├── app.component.html │ ├── service │ │ ├── index.ts │ │ ├── convert-request.service.ts │ │ ├── localstorage.service.ts │ │ ├── shop.service.ts │ │ ├── app.service.ts │ │ └── cart.service.ts │ ├── shop │ │ ├── evaluate │ │ │ ├── evaluate.page.html │ │ │ ├── evaluate.module.ts │ │ │ └── evaluate.page.ts │ │ ├── detail │ │ │ ├── shop-detail.module.ts │ │ │ ├── shop-detail.page.ts │ │ │ └── shop-detail.page.html │ │ └── shop.module.ts │ ├── food │ │ └── food.module.ts │ ├── home │ │ ├── home.module.ts │ │ ├── home.page.html │ │ ├── home.page.ts │ │ └── home.page.scss │ ├── city │ │ ├── city.module.ts │ │ ├── city.page.html │ │ ├── city.page.scss │ │ └── city.page.ts │ ├── login │ │ ├── login.module.ts │ │ ├── login.page.html │ │ ├── login.page.scss │ │ └── login.page.ts │ ├── msite │ │ ├── msite.module.ts │ │ ├── msite.page.scss │ │ ├── msite.page.html │ │ └── msite.page.ts │ ├── search │ │ ├── search.module.ts │ │ ├── search.page.html │ │ ├── search.page.scss │ │ └── search.page.ts │ ├── profile │ │ ├── profile.module.ts │ │ ├── profile.page.ts │ │ ├── profile.page.html │ │ └── profile.page.scss │ ├── order │ │ ├── order-detail │ │ │ ├── order-detail.module.ts │ │ │ ├── order-detail.page.ts │ │ │ ├── order-detail.page.html │ │ │ └── order-detail.page.scss │ │ ├── order.module.ts │ │ ├── time-last.pipe.ts │ │ ├── order.page.html │ │ ├── order.page.ts │ │ └── order.page.scss │ ├── confirm-order │ │ ├── remark │ │ │ ├── remark.module.ts │ │ │ ├── remark.page.html │ │ │ ├── remark.page.ts │ │ │ └── remark.page.scss │ │ ├── choose-address │ │ │ ├── choose-address.module.ts │ │ │ ├── choose-address.page.scss │ │ │ ├── choose-address.page.ts │ │ │ └── choose-address.page.html │ │ ├── payment │ │ │ ├── payment.module.ts │ │ │ ├── time-last.pipe.ts │ │ │ ├── payment.page.html │ │ │ ├── payment.page.ts │ │ │ └── payment.page.scss │ │ └── confirm-order.module.ts │ ├── address │ │ ├── add-address │ │ │ ├── add-address.module.ts │ │ │ ├── add-address.page.scss │ │ │ ├── add-address.page.html │ │ │ └── add-address.page.ts │ │ ├── search-address │ │ │ ├── search-address.module.ts │ │ │ ├── search-address.page.html │ │ │ ├── search-address.page.ts │ │ │ └── search-address.page.scss │ │ ├── address.module.ts │ │ ├── address.page.ts │ │ ├── address.page.html │ │ └── address.page.scss │ ├── app.component.ts │ ├── app-routing.module.ts │ └── app.module.ts ├── assets │ ├── imgs │ │ ├── logo.png │ │ ├── qq.png │ │ ├── jifen.jpeg │ │ ├── no-log.png │ │ ├── order.png │ │ ├── search.png │ │ ├── sheng.jpeg │ │ ├── weixin.png │ │ ├── activity.png │ │ ├── add_phone.png │ │ ├── bindphone.png │ │ ├── elmlogo.jpeg │ │ ├── expired.png │ │ ├── fenxiang.png │ │ ├── hongbao.png │ │ ├── qianbao.png │ │ ├── voucher.png │ │ ├── zhifubao.png │ │ ├── add_address.png │ │ ├── description.png │ │ ├── icon_point.png │ │ ├── address_bottom.png │ │ ├── icon_loading.png │ │ ├── shopback.svg │ │ └── fl.svg │ ├── icon │ │ ├── favicon.png │ │ ├── mine.svg │ │ ├── elm.svg │ │ └── find.svg │ ├── rem.js │ └── shapes.svg ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── proxy.conf.json ├── zone-flags.ts ├── main.ts ├── test.ts ├── index.html ├── global.scss ├── style │ ├── common.scss │ ├── ionic.scss │ └── mixin.scss └── polyfills.ts ├── ionic.config.json ├── resources ├── icon.png ├── splash.png ├── ios │ ├── icon │ │ ├── icon.png │ │ ├── icon-40.png │ │ ├── icon-50.png │ │ ├── icon-60.png │ │ ├── icon-72.png │ │ ├── icon-76.png │ │ ├── icon@2x.png │ │ ├── icon-1024.png │ │ ├── icon-40@2x.png │ │ ├── icon-40@3x.png │ │ ├── icon-50@2x.png │ │ ├── icon-60@2x.png │ │ ├── icon-60@3x.png │ │ ├── icon-72@2x.png │ │ ├── icon-76@2x.png │ │ ├── icon-small.png │ │ ├── icon-83.5@2x.png │ │ ├── icon-small@2x.png │ │ └── icon-small@3x.png │ └── splash │ │ ├── Default-667h.png │ │ ├── Default-736h.png │ │ ├── Default~iphone.png │ │ ├── Default@2x~iphone.png │ │ ├── Default-Portrait~ipad.png │ │ ├── Default-568h@2x~iphone.png │ │ ├── Default-Landscape-736h.png │ │ ├── Default-Landscape~ipad.png │ │ ├── Default-Portrait@2x~ipad.png │ │ ├── Default-Landscape@2x~ipad.png │ │ ├── Default-Landscape@~ipadpro.png │ │ ├── Default-Portrait@~ipadpro.png │ │ └── Default@2x~universal~anyany.png ├── 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-port-hdpi-screen.png │ │ ├── drawable-port-ldpi-screen.png │ │ ├── drawable-port-mdpi-screen.png │ │ ├── drawable-land-xhdpi-screen.png │ │ ├── drawable-land-xxhdpi-screen.png │ │ ├── drawable-port-xhdpi-screen.png │ │ ├── drawable-port-xxhdpi-screen.png │ │ ├── drawable-land-xxxhdpi-screen.png │ │ └── drawable-port-xxxhdpi-screen.png └── README.md ├── screenshots ├── food.gif ├── login.gif ├── msite.gif ├── shop1.gif ├── shop2.gif ├── tabs.gif └── search.gif ├── .gitattributes ├── e2e ├── tsconfig.e2e.json ├── src │ ├── app.po.ts │ └── app.e2e-spec.ts ├── tsconfig.json └── protractor.conf.js ├── tsconfig.spec.json ├── tsconfig.app.json ├── browserslist ├── tsconfig.json ├── .gitignore ├── karma.conf.js ├── package.json ├── README.md └── tslint.json /src/app/shared/components/shop/list/shop-list.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/class/index.ts: -------------------------------------------------------------------------------- 1 | export * from './userinfo'; 2 | -------------------------------------------------------------------------------- /src/app/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core.module'; 2 | -------------------------------------------------------------------------------- /src/app/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './shared.module'; 2 | -------------------------------------------------------------------------------- /src/app/tabs/tabs.page.scss: -------------------------------------------------------------------------------- 1 | ion-tabbar { 2 | height: 2rem; 3 | } -------------------------------------------------------------------------------- /src/app/shared/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components.module'; 2 | -------------------------------------------------------------------------------- /ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elmApp", 3 | "integrations": {}, 4 | "type": "angular" 5 | } 6 | -------------------------------------------------------------------------------- /resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/icon.png -------------------------------------------------------------------------------- /resources/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/splash.png -------------------------------------------------------------------------------- /screenshots/food.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/screenshots/food.gif -------------------------------------------------------------------------------- /screenshots/login.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/screenshots/login.gif -------------------------------------------------------------------------------- /screenshots/msite.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/screenshots/msite.gif -------------------------------------------------------------------------------- /screenshots/shop1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/screenshots/shop1.gif -------------------------------------------------------------------------------- /screenshots/shop2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/screenshots/shop2.gif -------------------------------------------------------------------------------- /screenshots/tabs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/screenshots/tabs.gif -------------------------------------------------------------------------------- /src/app/config/env.ts: -------------------------------------------------------------------------------- 1 | const ImgBaseUrl = 'http://cangdu.org:8001/img/'; 2 | 3 | export {ImgBaseUrl}; 4 | -------------------------------------------------------------------------------- /screenshots/search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/screenshots/search.gif -------------------------------------------------------------------------------- /src/assets/imgs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/logo.png -------------------------------------------------------------------------------- /src/assets/imgs/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/qq.png -------------------------------------------------------------------------------- /src/assets/imgs/jifen.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/jifen.jpeg -------------------------------------------------------------------------------- /src/assets/imgs/no-log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/no-log.png -------------------------------------------------------------------------------- /src/assets/imgs/order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/order.png -------------------------------------------------------------------------------- /src/assets/imgs/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/search.png -------------------------------------------------------------------------------- /src/assets/imgs/sheng.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/sheng.jpeg -------------------------------------------------------------------------------- /src/assets/imgs/weixin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/weixin.png -------------------------------------------------------------------------------- /resources/ios/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon.png -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/icon/favicon.png -------------------------------------------------------------------------------- /src/assets/imgs/activity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/activity.png -------------------------------------------------------------------------------- /src/assets/imgs/add_phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/add_phone.png -------------------------------------------------------------------------------- /src/assets/imgs/bindphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/bindphone.png -------------------------------------------------------------------------------- /src/assets/imgs/elmlogo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/elmlogo.jpeg -------------------------------------------------------------------------------- /src/assets/imgs/expired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/expired.png -------------------------------------------------------------------------------- /src/assets/imgs/fenxiang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/fenxiang.png -------------------------------------------------------------------------------- /src/assets/imgs/hongbao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/hongbao.png -------------------------------------------------------------------------------- /src/assets/imgs/qianbao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/qianbao.png -------------------------------------------------------------------------------- /src/assets/imgs/voucher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/voucher.png -------------------------------------------------------------------------------- /src/assets/imgs/zhifubao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/zhifubao.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-40.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-50.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-60.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-72.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-76.png -------------------------------------------------------------------------------- /resources/ios/icon/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon@2x.png -------------------------------------------------------------------------------- /src/assets/imgs/add_address.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/add_address.png -------------------------------------------------------------------------------- /src/assets/imgs/description.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/description.png -------------------------------------------------------------------------------- /src/assets/imgs/icon_point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/icon_point.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-1024.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-40@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-40@3x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-50@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-60@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-60@3x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-72@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-76@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-small.png -------------------------------------------------------------------------------- /src/assets/imgs/address_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/address_bottom.png -------------------------------------------------------------------------------- /src/assets/imgs/icon_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/src/assets/imgs/icon_loading.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-83.5@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-small@2x.png -------------------------------------------------------------------------------- /resources/ios/icon/icon-small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/icon/icon-small@3x.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-667h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-667h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-736h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default~iphone.png -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | apiUrl: 'http://cangdu.org:8001' 4 | }; 5 | -------------------------------------------------------------------------------- /resources/ios/splash/Default@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default@2x~iphone.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-hdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/icon/drawable-hdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-ldpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/icon/drawable-ldpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-mdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/icon/drawable-mdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-xhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/icon/drawable-xhdpi-icon.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-Portrait~ipad.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-xxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/icon/drawable-xxhdpi-icon.png -------------------------------------------------------------------------------- /resources/android/icon/drawable-xxxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/icon/drawable-xxxhdpi-icon.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-568h@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-568h@2x~iphone.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-Landscape-736h.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-Landscape~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-Portrait@2x~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-Landscape@2x~ipad.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Landscape@~ipadpro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-Landscape@~ipadpro.png -------------------------------------------------------------------------------- /resources/ios/splash/Default-Portrait@~ipadpro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default-Portrait@~ipadpro.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-land-hdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-land-ldpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-land-mdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-port-hdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-port-ldpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-port-mdpi-screen.png -------------------------------------------------------------------------------- /resources/ios/splash/Default@2x~universal~anyany.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/ios/splash/Default@2x~universal~anyany.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-land-xhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-land-xxhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-port-xhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-port-xxhdpi-screen.png -------------------------------------------------------------------------------- /src/proxy.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "/": { 3 | "target": "https://elm.cangdu.org", 4 | "changeOrigin": true, 5 | "secure": false, 6 | "logLevel": "debug" 7 | } 8 | } -------------------------------------------------------------------------------- /resources/android/splash/drawable-land-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-land-xxxhdpi-screen.png -------------------------------------------------------------------------------- /resources/android/splash/drawable-port-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nuonuoge/ionic6_angular10_elm/HEAD/resources/android/splash/drawable-port-xxxhdpi-screen.png -------------------------------------------------------------------------------- /src/zone-flags.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Prevents Angular change detection from 3 | * running with certain Web Component callbacks 4 | */ 5 | (window as any).__Zone_disable_customElements = true; 6 | -------------------------------------------------------------------------------- /src/app/service/index.ts: -------------------------------------------------------------------------------- 1 | export * from './data.service'; 2 | export * from './localstorage.service'; 3 | export * from './cart.service'; 4 | export * from './shop.service'; 5 | export * from './app.service'; 6 | -------------------------------------------------------------------------------- /src/app/shared/components/svg/svg.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'elm-svg', 5 | templateUrl: 'svg.html' 6 | }) 7 | export class ElmSvgComponent { 8 | } 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | *.ts linguist-language=TypeScript 3 | *.js linguist-language=TypeScript 4 | *.html linguist-language=TypeScript 5 | *.scss linguist-language=TypeScript -------------------------------------------------------------------------------- /e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shop/evaluate/evaluate.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getPageTitle() { 9 | return element(by.css('ion-title')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/app/tabs/tabs.page.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-tabs', 5 | templateUrl: 'tabs.page.html', 6 | styleUrls: ['tabs.page.scss'] 7 | }) 8 | export class TabsPage { 9 | constructor() { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/app/shared/components/login-header/login-header.html: -------------------------------------------------------------------------------- 1 | 登录|注册 2 | 3 | 4 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/app/shared/components/rating-star/rating-star.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'rating-star', 5 | templateUrl: 'rating-star.html', 6 | styleUrls: ['rating-star.scss'] 7 | }) 8 | export class RatingStarComponent { 9 | @Input() rating: number; 10 | } 11 | -------------------------------------------------------------------------------- /e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | 3 | describe('new App', () => { 4 | let page: AppPage; 5 | 6 | beforeEach(() => { 7 | page = new AppPage(); 8 | }); 9 | 10 | it('should display welcome message', () => { 11 | page.navigateTo(); 12 | expect(page.getPageTitle()).toContain('Tab 1'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } -------------------------------------------------------------------------------- /src/app/shared/components/loading/loading.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 6 | 7 |
-------------------------------------------------------------------------------- /src/app/core/core.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | @NgModule({ 5 | imports: [ 6 | CommonModule, 7 | FormsModule 8 | ], 9 | declarations: [ 10 | ], 11 | exports: [ 12 | ], 13 | entryComponents: [] 14 | }) 15 | export class CoreModule {} 16 | -------------------------------------------------------------------------------- /src/app/shared/components/login-header/login-header.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../style/mixin.scss"; 2 | :host { 3 | position: absolute; 4 | right: 0; 5 | top: calc(50% - .55rem); 6 | font-size: 1.1rem; 7 | } 8 | .login_span { 9 | margin-right: .8rem; 10 | color: #fff; 11 | } 12 | .user_avatar { 13 | margin-right: .8rem; 14 | @include wh(1.33rem, 1.33rem); 15 | fill: #fff; 16 | } -------------------------------------------------------------------------------- /src/app/shared/components/shop/list/shop-list.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'shop-list', 5 | templateUrl: 'shop-list.html' 6 | }) 7 | export class ShoplistComponent { 8 | @Input() shopList: any; 9 | @Input() type: string; 10 | @Input() geohash: string; 11 | touchend: boolean; 12 | showBackStatus: string; 13 | constructor() { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/app/food/food.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../shared'; 4 | import { FoodPage } from './food.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([{ path: '', component: FoodPage }]) 10 | ], 11 | declarations: [FoodPage] 12 | }) 13 | export class FoodPageModule {} 14 | -------------------------------------------------------------------------------- /src/app/home/home.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../shared'; 4 | import { HomePage } from './home.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([{ path: '', component: HomePage }]) 10 | ], 11 | declarations: [HomePage] 12 | }) 13 | export class HomePageModule {} 14 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.log(err)); 13 | -------------------------------------------------------------------------------- /src/app/city/city.module.ts: -------------------------------------------------------------------------------- 1 | 2 | import { RouterModule } from '@angular/router'; 3 | import { NgModule } from '@angular/core'; 4 | import { SharedModule } from '../shared'; 5 | import { CityPage } from './city.page'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | SharedModule, 10 | RouterModule.forChild([{ path: '', component: CityPage }]) 11 | ], 12 | declarations: [CityPage] 13 | }) 14 | export class CityPageModule {} 15 | -------------------------------------------------------------------------------- /src/app/login/login.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../shared'; 4 | import { LoginPage } from './login.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([{ path: '', component: LoginPage }]) 10 | ], 11 | declarations: [LoginPage] 12 | }) 13 | export class LoginPageModule {} 14 | -------------------------------------------------------------------------------- /src/app/msite/msite.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../shared'; 4 | import { MsitePage } from './msite.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([{ path: '', component: MsitePage }]) 10 | ], 11 | declarations: [MsitePage] 12 | }) 13 | export class MsitePageModule {} 14 | -------------------------------------------------------------------------------- /src/app/shared/components/shop/search/shop-search.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | import { ImgBaseUrl } from '../../../../config/env'; 3 | 4 | @Component({ 5 | selector: 'shop-search', 6 | templateUrl: 'shop-search.html', 7 | styleUrls: ['shop-search.scss'] 8 | }) 9 | export class ShopSearchComponent { 10 | @Input() shop: any; 11 | imgBaseUrl = ImgBaseUrl; 12 | constructor() { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/app/search/search.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../shared'; 4 | import { SearchPage } from './search.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([{ path: '', component: SearchPage }]) 10 | ], 11 | declarations: [SearchPage] 12 | }) 13 | export class SearchPageModule {} 14 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts", 9 | "src/polyfills.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.ts", 13 | "src/**/*.d.ts" 14 | ], 15 | "exclude": [ 16 | "src/test.ts", 17 | "src/**/*.spec.ts", 18 | "src/environments/environment.prod.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/app/profile/profile.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../shared'; 4 | import { ProfilePage } from './profile.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([{ path: '', component: ProfilePage }]) 10 | ], 11 | declarations: [ProfilePage] 12 | }) 13 | export class ProfilePageModule {} 14 | -------------------------------------------------------------------------------- /resources/README.md: -------------------------------------------------------------------------------- 1 | These are Cordova resources. You can replace icon.png and splash.png and run 2 | `ionic cordova resources` to generate custom icons and splash screens for your 3 | app. See `ionic cordova resources --help` for details. 4 | 5 | Cordova reference documentation: 6 | 7 | - Icons: https://cordova.apache.org/docs/en/latest/config_ref/images.html 8 | - Splash Screens: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-splashscreen/ 9 | -------------------------------------------------------------------------------- /src/app/shop/detail/shop-detail.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../../shared'; 4 | import { ShopDetailPage } from './shop-detail.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([{ path: '', component: ShopDetailPage }]) 10 | ], 11 | declarations: [ShopDetailPage] 12 | }) 13 | export class ShopDetailPageModule {} 14 | 15 | -------------------------------------------------------------------------------- /src/app/shop/evaluate/evaluate.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../../shared'; 4 | import { ShopEvaluatePage } from './evaluate.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([{ path: '', component: ShopEvaluatePage }]) 10 | ], 11 | declarations: [ShopEvaluatePage] 12 | }) 13 | export class ShopEvaluatePageModule {} 14 | -------------------------------------------------------------------------------- /browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. 13 | -------------------------------------------------------------------------------- /src/app/order/order-detail/order-detail.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule } from '@angular/router'; 3 | import { SharedModule } from '../../shared'; 4 | import { OrderDetailPage } from './order-detail.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([{ path: '', component: OrderDetailPage }]) 10 | ], 11 | declarations: [OrderDetailPage] 12 | }) 13 | export class OrderDetailPageModule {} 14 | 15 | -------------------------------------------------------------------------------- /src/app/shared/components/back/back-header.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'back-header', 5 | template: ` 6 | 7 | 8 | {{hTitle}} 9 | 10 | `, 11 | styles: [` 12 | .back-icon { 13 | margin: 0 -5px 0 -4px; 14 | } 15 | `] 16 | }) 17 | export class BackHeaderComponent { 18 | @Input() hTitle: string; 19 | } 20 | -------------------------------------------------------------------------------- /src/app/confirm-order/remark/remark.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../../shared'; 4 | import { RemarkPage } from './remark.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([ 10 | { 11 | path: '', component: RemarkPage 12 | } 13 | ]) 14 | ], 15 | declarations: [RemarkPage] 16 | }) 17 | export class RemarkPageModule { } 18 | 19 | -------------------------------------------------------------------------------- /src/app/order/order.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule } from '@angular/router'; 3 | import { SharedModule } from '../shared'; 4 | import { OrderPage } from './order.page'; 5 | import { TimeLastPipe } from './time-last.pipe'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | SharedModule, 10 | RouterModule.forChild([ 11 | { path: '', component: OrderPage } 12 | ]) 13 | ], 14 | declarations: [OrderPage, TimeLastPipe] 15 | }) 16 | export class OrderPageModule {} 17 | -------------------------------------------------------------------------------- /src/app/address/add-address/add-address.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../../shared'; 4 | import { AddAddressPage } from './add-address.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([ 10 | { 11 | path: '', component: AddAddressPage 12 | } 13 | ]) 14 | ], 15 | declarations: [AddAddressPage] 16 | }) 17 | export class AddAddressPageModule { } 18 | 19 | -------------------------------------------------------------------------------- /src/assets/rem.js: -------------------------------------------------------------------------------- 1 | (function (doc, win) { 2 | var docEl = doc.documentElement, 3 | resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', 4 | recalc = function () { 5 | var clientWidth = docEl.clientWidth; 6 | if (!clientWidth) return; 7 | docEl.style.fontSize = 12 * (clientWidth / 320) + 'px'; 8 | }; 9 | if (!doc.addEventListener) return; 10 | win.addEventListener(resizeEvt, recalc, false); 11 | doc.addEventListener('DOMContentLoaded', recalc, false); 12 | })(document, window); -------------------------------------------------------------------------------- /src/app/address/search-address/search-address.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../../shared'; 4 | import { SearchAddressPage } from './search-address.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([ 10 | { 11 | path: '', component: SearchAddressPage 12 | } 13 | ]) 14 | ], 15 | declarations: [SearchAddressPage] 16 | }) 17 | export class SearchAddressPageModule { } 18 | 19 | -------------------------------------------------------------------------------- /src/app/confirm-order/choose-address/choose-address.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../../shared'; 4 | import { ChooseAddressPage } from './choose-address.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([ 10 | { 11 | path: '', component: ChooseAddressPage 12 | } 13 | ]) 14 | ], 15 | declarations: [ChooseAddressPage] 16 | }) 17 | export class ChooseAddressPageModule { } 18 | 19 | -------------------------------------------------------------------------------- /src/app/confirm-order/payment/payment.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../../shared'; 4 | import { PaymentPage } from './payment.page'; 5 | import { TimeLastPipe } from './time-last.pipe'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | SharedModule, 10 | RouterModule.forChild([ 11 | { 12 | path: '', component: PaymentPage 13 | } 14 | ]) 15 | ], 16 | declarations: [PaymentPage, TimeLastPipe] 17 | }) 18 | export class PaymentPageModule { } 19 | 20 | -------------------------------------------------------------------------------- /src/app/shared/components/loading/loading.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnDestroy } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'loading', 5 | templateUrl: 'loading.html', 6 | styleUrls: ['loading.scss'] 7 | }) 8 | export class LoadingComponent implements OnDestroy { 9 | timer: any; 10 | positionY: number; 11 | constructor() { 12 | this.positionY = 0; 13 | this.timer = setInterval(() => { 14 | this.positionY++; 15 | }, 600); 16 | } 17 | ngOnDestroy() { 18 | if (this.timer) { 19 | clearInterval(this.timer); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/app/confirm-order/payment/time-last.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | 3 | @Pipe({ name: 'timeLast' }) 4 | export class TimeLastPipe implements PipeTransform { 5 | transform(value: number, ...args: any[]): string { 6 | let minute: any = parseInt((value / 60).toString(), 10); 7 | if (minute < 10) { 8 | minute = '0' + minute; 9 | } 10 | let second: any = parseInt((value % 60).toString(), 10); 11 | if (second < 10) { 12 | second = '0' + second; 13 | } 14 | return '00 : ' + minute + ' : ' + second; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "importHelpers": true, 13 | "target": "es2015", 14 | "lib": [ 15 | "es2018", 16 | "dom" 17 | ] 18 | }, 19 | "angularCompilerOptions": { 20 | "fullTemplateTypeCheck": true, 21 | "strictInjectionParameters": true 22 | } 23 | } -------------------------------------------------------------------------------- /src/app/shop/evaluate/evaluate.page.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | 4 | 5 | @Component({ 6 | selector: 'page-shop-evaluate', 7 | templateUrl: 'evaluate.page.html' 8 | }) 9 | export class ShopEvaluatePage { 10 | shopId: string; 11 | rating: string; 12 | title: string; 13 | constructor(public route: ActivatedRoute) { 14 | this.shopId = this.route.snapshot.paramMap.get('id'); 15 | this.rating = this.route.snapshot.queryParamMap.get('rating'); 16 | this.title = this.route.snapshot.queryParamMap.get('title'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/app/shared/components/rating-star/rating-star.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../style/mixin.scss"; 2 | .rating_container{ 3 | position: relative; 4 | top: .334rem; 5 | @include wh(3.34rem, .668rem); 6 | .star_overflow{ 7 | overflow: hidden; 8 | position: relative; 9 | height: 100%; 10 | } 11 | .star_container{ 12 | position: absolute; 13 | display: flex; 14 | width: 3.34rem; 15 | height: 0.668rem; 16 | top: -0.0334rem; 17 | left: -0.0334rem; 18 | .grey_fill{ 19 | fill: #d1d1d1; 20 | } 21 | .orange_fill{ 22 | fill: #ff9a0d; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { IonicModule } from '@ionic/angular'; 5 | import { ComponentsModule } from './components'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | FormsModule, 11 | IonicModule.forRoot(), 12 | ], 13 | declarations: [ 14 | ], 15 | exports: [ 16 | CommonModule, 17 | FormsModule, 18 | IonicModule, 19 | ComponentsModule 20 | ], 21 | entryComponents: [], 22 | }) 23 | export class SharedModule {} 24 | -------------------------------------------------------------------------------- /src/app/shared/components/rating-star/rating-star.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | 6 |
7 |
8 |
9 | 10 | 11 | 12 |
13 |
14 |
-------------------------------------------------------------------------------- /.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 | ionic-elm/ 18 | ionic-ng-elm/ 19 | .sass-cache/ 20 | .tmp/ 21 | .versions/ 22 | coverage/ 23 | dist/ 24 | node_modules/ 25 | tmp/ 26 | temp/ 27 | hooks/ 28 | platforms/ 29 | plugins/ 30 | plugins/android.json 31 | plugins/ios.json 32 | www/ 33 | $RECYCLE.BIN/ 34 | 35 | .DS_Store 36 | Thumbs.db 37 | UserInterfaceState.xcuserstate 38 | -------------------------------------------------------------------------------- /src/app/service/convert-request.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http'; 3 | import { Observable } from 'rxjs'; 4 | import { environment } from '../../environments/environment'; 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | export class ConvertRequestService implements HttpInterceptor { 10 | 11 | intercept(req: HttpRequest, next: HttpHandler): Observable> { 12 | const convertReq = req.clone({ 13 | url: environment.apiUrl + req.url 14 | }); 15 | return next.handle(convertReq); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/shared/components/back/back-icon.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'back-icon', 5 | template: ``, 6 | styles: [` 7 | ion-icon { 8 | font-size: 1.4rem; 9 | margin: auto 0; 10 | } 11 | `] 12 | }) 13 | export class BackIconComponent { 14 | _size: number = 2; 15 | @Input() set size(val: string) { 16 | if (val === 'md') { 17 | this._size = 2; 18 | } else if (val === 'sm') { 19 | this._size = 1.4; 20 | } 21 | } 22 | back() { 23 | window.history.back(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/app/shared/components/shop/list/shop-list.html: -------------------------------------------------------------------------------- 1 |
2 |
    3 | 4 | 5 | 6 |
7 |
    8 | 9 | 10 | 11 |
12 |
    13 |
  • 14 | 15 |
  • 16 |
17 |
-------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | import { Platform } from '@ionic/angular'; 4 | import { SplashScreen } from '@ionic-native/splash-screen/ngx'; 5 | import { StatusBar } from '@ionic-native/status-bar/ngx'; 6 | 7 | @Component({ 8 | selector: 'app-root', 9 | templateUrl: 'app.component.html' 10 | }) 11 | export class AppComponent { 12 | constructor( 13 | private platform: Platform, 14 | private splashScreen: SplashScreen, 15 | private statusBar: StatusBar 16 | ) { 17 | this.initializeApp(); 18 | } 19 | 20 | initializeApp() { 21 | this.platform.ready().then(() => { 22 | this.statusBar.styleDefault(); 23 | this.splashScreen.hide(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/service/localstorage.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | 7 | export class LocalStorageService { 8 | 9 | getStore(name: string) { 10 | if (!name) { 11 | return; 12 | } 13 | return window.localStorage.getItem(name); 14 | } 15 | 16 | setStore(name: string, content: any) { 17 | if (!name) { 18 | return; 19 | } 20 | if (typeof content !== 'string') { 21 | content = JSON.stringify(content); 22 | } 23 | window.localStorage.setItem(name, content); 24 | } 25 | 26 | removeStore(name: string) { 27 | if (!name) { 28 | return; 29 | } 30 | window.localStorage.removeItem(name); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/shared/components/login-header/login-header.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { AppService, LocalStorageService } from '../../../service'; 4 | import { UserInfo } from '../../../class'; 5 | 6 | @Component({ 7 | selector: 'login-header', 8 | templateUrl: 'login-header.html', 9 | styleUrls: ['login-header.scss'] 10 | }) 11 | export class LoginHeaderComponent extends UserInfo { 12 | constructor(public router: Router, 13 | public localStorageService: LocalStorageService, 14 | public appService: AppService) { 15 | super(appService, localStorageService); 16 | } 17 | 18 | public toProfile() { 19 | this.router.navigateByUrl('/tabs/profile'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/tabs/tabs.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 外卖 6 | 7 | 8 | 9 | 10 | 搜索 11 | 12 | 13 | 14 | 15 | 订单 16 | 17 | 18 | 19 | 20 | 我的 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/app/tabs/tabs.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule } from '../shared'; 3 | 4 | import { TabsPageRoutingModule } from './tabs.router.module'; 5 | 6 | import { TabsPage } from './tabs.page'; 7 | import { MsitePageModule } from '../msite/msite.module'; 8 | import { SearchPageModule } from '../search/search.module'; 9 | import { ProfilePageModule } from '../profile/profile.module'; 10 | import { OrderPageModule } from '../order/order.module'; 11 | 12 | @NgModule({ 13 | imports: [ 14 | SharedModule, 15 | TabsPageRoutingModule, 16 | MsitePageModule, 17 | SearchPageModule, 18 | ProfilePageModule, 19 | OrderPageModule 20 | ], 21 | declarations: [TabsPage] 22 | }) 23 | export class TabsPageModule {} 24 | -------------------------------------------------------------------------------- /src/app/service/shop.service.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter, Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | 7 | export class ShopService { 8 | shopDetailData: any; 9 | ratingScoresData: any; 10 | ratingList: any; 11 | updateData: EventEmitter = new EventEmitter(); 12 | loaderMoreRatings: EventEmitter = new EventEmitter(); 13 | 14 | setShopDetailData(data: any) { 15 | this.shopDetailData = data; 16 | this.updateData.emit('update'); 17 | } 18 | 19 | setRatingScoresData(data: any) { 20 | this.ratingScoresData = data; 21 | this.updateData.emit('update'); 22 | } 23 | 24 | setRatingList(data: any) { 25 | this.ratingList = data; 26 | this.updateData.emit('update'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/address/address.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../shared'; 4 | import { AddressPage } from './address.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([ 10 | { 11 | path: '', 12 | component: AddressPage, 13 | }, 14 | { 15 | path: 'add', 16 | loadChildren: () => import('./add-address/add-address.module').then(m => m.AddAddressPageModule) 17 | }, 18 | { 19 | path: 'search', 20 | loadChildren: () => import('./search-address/search-address.module').then(m => m.SearchAddressPageModule) 21 | } 22 | ]) 23 | ], 24 | declarations: [AddressPage] 25 | }) 26 | export class AddressPageModule { } 27 | -------------------------------------------------------------------------------- /src/app/service/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, EventEmitter } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | 7 | export class AppService { 8 | public userInfoEvent: EventEmitter = new EventEmitter(); 9 | public notify: EventEmitter = new EventEmitter(); 10 | public geohash: string = ''; 11 | public shopId: string = ''; 12 | public searchAddress: any; 13 | public choosedAddress: { address: string, index: number } = { address: '', index: 0 }; 14 | public confirmRemark: { remarkText: string, inputText: string } = { remarkText: '', inputText: '' }; 15 | public orderDetail: any; 16 | 17 | getTabPagesIndex(pageName) { 18 | const tabPagesIndex: any = { MsitePage: 0, SearchPage: 1, OrderPage: 2, ProfilePage: 3 }; 19 | return tabPagesIndex[pageName]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/assets/imgs/shopback.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/class/userinfo.ts: -------------------------------------------------------------------------------- 1 | import { Directive, OnDestroy, OnInit } from '@angular/core'; 2 | import { AppService, LocalStorageService } from '../service'; 3 | import { Subscription } from 'rxjs'; 4 | @Directive() 5 | export class UserInfo implements OnInit, OnDestroy { 6 | public userId: string; 7 | unSubEvent: Subscription; 8 | constructor(public appService: AppService, 9 | public localStorageService: LocalStorageService) { 10 | this.userId = this.localStorageService.getStore('userId'); 11 | this.unSubEvent = this.appService.userInfoEvent.subscribe(res => { 12 | this.userId = this.localStorageService.getStore('userId'); 13 | this.ngOnInit(); 14 | }); 15 | } 16 | ngOnInit() {} 17 | 18 | ngOnDestroy() { 19 | if (this.unSubEvent) { 20 | this.unSubEvent.unsubscribe(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | export const environment = { 6 | production: false, 7 | apiUrl: '' 8 | }; 9 | 10 | /* 11 | * In development mode, to ignore zone related error stack frames such as 12 | * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can 13 | * import the following file, but please comment it out in production mode 14 | * because it will have performance impact when throw error 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /src/app/shop/shop.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../shared'; 4 | import { ShopPage } from './shop.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([ 10 | { path: '', redirectTo: ':id', pathMatch: 'full' }, 11 | { 12 | path: ':id', 13 | children: [ 14 | { path: '', component: ShopPage }, 15 | { path: 'detail', loadChildren: () => import('./detail/shop-detail.module').then(m => m.ShopDetailPageModule) }, 16 | { path: 'evaluate', loadChildren: () => import('./evaluate/evaluate.module').then(m => m.ShopEvaluatePageModule) } 17 | ] 18 | } 19 | ]) 20 | ], 21 | declarations: [ShopPage] 22 | }) 23 | export class ShopPageModule { } 24 | -------------------------------------------------------------------------------- /src/app/order/time-last.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | 3 | @Pipe({ name: 'timeLast', pure: false }) 4 | export class TimeLastPipe implements PipeTransform { 5 | timer: any; 6 | countNum: number = 900; 7 | constructor() { 8 | setInterval(() => { 9 | this.countNum--; 10 | if (this.countNum === 0) { 11 | clearInterval(this.timer); 12 | } 13 | }, 1000); 14 | } 15 | transform(value: number, ...args: any[]): string { 16 | const time = this.countNum - value; 17 | let minute: any = parseInt((time / 60).toString(), 10); 18 | let second: any = parseInt((time % 60).toString(), 10); 19 | if (minute < 10) { 20 | minute = '0' + minute; 21 | } 22 | if (second < 10) { 23 | second = '0' + second; 24 | } 25 | return '去支付(还剩' + minute + '分' + second + '秒)'; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/app/address/search-address/search-address.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 |
8 | 9 | 10 |
11 |
    12 |
  • 13 |

    {{item.name}}

    14 |

    {{item.address}}

    15 |
  • 16 |
17 |
18 |

找不到地址?

19 |

尝试输入小区、写字楼或学校名

20 |

详细地址(如门牌号等)可稍后输入哦

21 |
22 |
23 |
24 |
-------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | elm 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/app/address/search-address/search-address.page.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { DataService, AppService} from '../../service'; 4 | 5 | @Component({ 6 | selector: 'page-search-address', 7 | templateUrl: 'search-address.page.html', 8 | styleUrls: ['search-address.page.scss'] 9 | }) 10 | export class SearchAddressPage { 11 | searchData: any; 12 | searchValue: string = ''; 13 | constructor( 14 | public router: Router, 15 | public appService: AppService, 16 | public dataService: DataService) { 17 | } 18 | 19 | searchPlace() { 20 | if (this.searchValue) { 21 | this.dataService.searchNearby(this.searchValue).subscribe(res => { 22 | this.searchData = res; 23 | }); 24 | } 25 | } 26 | choooedAddress(item: any) { 27 | this.appService.searchAddress = item; 28 | this.router.navigate(['/address', 'add']); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/address/address.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { AppService, DataService, LocalStorageService } from '../service'; 3 | import { UserInfo } from '../class'; 4 | @Component({ 5 | selector: 'page-address', 6 | templateUrl: 'address.page.html', 7 | styleUrls: ['address.page.scss'] 8 | }) 9 | export class AddressPage extends UserInfo implements OnInit, OnDestroy { 10 | addressList: any[]; 11 | iconColor: any = {'公司': '#4cd964', '学校': '#3190e8', '家': '#ff5722'}; 12 | constructor( 13 | public appService: AppService, 14 | public localStorageService: LocalStorageService, 15 | public dataService: DataService) { 16 | super(appService, localStorageService); 17 | } 18 | 19 | ngOnInit() { 20 | this.addressList = []; 21 | if (this.userId) { 22 | this.dataService.getAddressList(this.userId).subscribe(res => { 23 | this.addressList = res; 24 | }); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/app/shared/components/loading/loading.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../style/mixin.scss"; 2 | @keyframes load{ 3 | 0% {transform: translateY(0px);} 4 | 50% {transform: translateY(-50px);} 5 | 100% {transform: translateY(0px);} 6 | } 7 | @keyframes ellipse{ 8 | 0% {transform: scale(1);} 9 | 50% {transform: scale(0.3);} 10 | 100% {transform: scale(1);} 11 | } 12 | .loading_container{ 13 | position: fixed; 14 | top: 50%; 15 | left: 50%; 16 | transform: translate(-50%, -50%); 17 | @include wh(2.5rem, 2.5rem); 18 | } 19 | .load_img{ 20 | @include wh(100%, 100%); 21 | background: url(../../../../assets/imgs/icon_loading.png) no-repeat 0 0; 22 | background-size: 2.5rem auto; 23 | transform: translateY(0px); 24 | animation: load .6s infinite ease-in-out; 25 | position: relative; 26 | z-index: 11; 27 | } 28 | .load_ellipse{ 29 | position: absolute; 30 | @include wh(2.6rem, 2rem); 31 | top: 2.2rem; 32 | left: 0.2rem; 33 | z-index: 10; 34 | animation: ellipse .6s infinite ease-in-out; 35 | } -------------------------------------------------------------------------------- /src/app/confirm-order/confirm-order.module.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { NgModule } from '@angular/core'; 3 | import { SharedModule } from '../shared'; 4 | import { ConfirmOrderPage } from './confirm-order.page'; 5 | 6 | @NgModule({ 7 | imports: [ 8 | SharedModule, 9 | RouterModule.forChild([ 10 | { 11 | path: '', 12 | component: ConfirmOrderPage, 13 | }, 14 | { 15 | path: 'chooseAddress', 16 | loadChildren: () => import('./choose-address/choose-address.module').then(m => m.ChooseAddressPageModule) 17 | }, 18 | { 19 | path: 'remark', 20 | loadChildren: () => import('./remark/remark.module').then(m => m.RemarkPageModule) 21 | }, 22 | { 23 | path: 'payment', 24 | loadChildren: () => import('./payment/payment.module').then(m => m.PaymentPageModule) 25 | } 26 | ]) 27 | ], 28 | declarations: [ConfirmOrderPage] 29 | }) 30 | export class ConfirmOrderPageModule { } 31 | -------------------------------------------------------------------------------- /src/app/shared/components/shop/msite/shop-msite.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | import { ImgBaseUrl } from '../../../../config/env'; 3 | 4 | @Component({ 5 | selector: 'shop-msite', 6 | templateUrl: 'shop-msite.html', 7 | styleUrls: ['shop-msite.scss'] 8 | }) 9 | export class ShopMsiteComponent { 10 | distance: number; 11 | _shop: any; 12 | @Input() 13 | set shop(val: any) { 14 | this._shop = val; 15 | if (val && val.distance) { 16 | this.distance = Number(val); 17 | } 18 | } 19 | get shop() { 20 | return this._shop; 21 | } 22 | @Input() geohash: string; 23 | imgBaseUrl = ImgBaseUrl; 24 | 25 | zhunShi(supports) { 26 | let zhunStatus; 27 | if ((supports instanceof Array) && supports.length) { 28 | supports.forEach(item => { 29 | if (item.icon_name === '准') { 30 | zhunStatus = true; 31 | } 32 | }); 33 | } else { 34 | zhunStatus = false; 35 | } 36 | return zhunStatus; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Protractor configuration file, see link for more information 3 | // https://github.com/angular/protractor/blob/master/lib/config.ts 4 | 5 | const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter'); 6 | 7 | /** 8 | * @type { import("protractor").Config } 9 | */ 10 | exports.config = { 11 | allScriptsTimeout: 11000, 12 | specs: [ 13 | './src/**/*.e2e-spec.ts' 14 | ], 15 | capabilities: { 16 | browserName: 'chrome' 17 | }, 18 | directConnect: true, 19 | baseUrl: 'http://localhost:4200/', 20 | framework: 'jasmine', 21 | jasmineNodeOpts: { 22 | showColors: true, 23 | defaultTimeoutInterval: 30000, 24 | print: function() {} 25 | }, 26 | onPrepare() { 27 | require('ts-node').register({ 28 | project: require('path').join(__dirname, './tsconfig.json') 29 | }); 30 | jasmine.getEnv().addReporter(new SpecReporter({ 31 | spec: { 32 | displayStacktrace: StacktraceOption.PRETTY 33 | } 34 | })); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /src/app/address/address.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 |
    8 |
  • 9 |
    10 |
    11 | {{item.name}} 12 | {{item.sex == 1? '先生' : '女士'}} 13 | {{item.phone}} 14 |
    15 |
    16 | {{item.tag}} 17 |

    {{item.address_detail}}

    18 |
    19 |
    20 |
  • 21 |
22 |
23 |
24 | 28 |
-------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../coverage'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /src/assets/shapes.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/city/city.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{guessCity}} 5 | 切换城市 6 | 7 | 8 | 9 | 10 |
11 | 14 |
15 | 提交 16 |
17 |
18 |
搜索历史
19 |
    20 |
  • 21 |

    {{place?.name}}

    22 |

    {{place?.address}}

    23 |
  • 24 |
25 |
清空所有
26 |
很抱歉!无搜索结果
27 |
-------------------------------------------------------------------------------- /src/app/tabs/tabs.router.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | 4 | import { TabsPage } from './tabs.page'; 5 | 6 | 7 | const routes: Routes = [ 8 | { 9 | path: '', 10 | component: TabsPage, 11 | children: [ 12 | { 13 | path: '', 14 | redirectTo: '/msite', 15 | pathMatch: 'full' 16 | }, 17 | { 18 | path: 'msite', 19 | loadChildren: () => import('../msite/msite.module').then(m => m.MsitePageModule) 20 | }, 21 | { 22 | path: 'search', 23 | loadChildren: () => import('../search/search.module').then(m => m.SearchPageModule) 24 | }, 25 | { 26 | path: 'order', 27 | loadChildren: () => import('../order/order.module').then(m => m.OrderPageModule) 28 | }, 29 | { 30 | path: 'profile', 31 | loadChildren: () => import('../profile/profile.module').then(m => m.ProfilePageModule) 32 | } 33 | ] 34 | } 35 | ]; 36 | 37 | @NgModule({ 38 | imports: [RouterModule.forChild(routes)], 39 | exports: [RouterModule] 40 | }) 41 | export class TabsPageRoutingModule { } 42 | -------------------------------------------------------------------------------- /src/global.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * App Global CSS 3 | * ---------------------------------------------------------------------------- 4 | * Put style rules here that you want to apply globally. These styles are for 5 | * the entire app and not just one component. Additionally, this file can be 6 | * used as an entry point to import other CSS/Sass files to be included in the 7 | * output CSS. 8 | * For more information on global stylesheets, visit the documentation: 9 | * https://ionicframework.com/docs/layout/global-stylesheets 10 | */ 11 | 12 | /* Core CSS required for Ionic components to work properly */ 13 | @import "~@ionic/angular/css/core.css"; 14 | 15 | /* Basic CSS for apps built with Ionic */ 16 | @import "~@ionic/angular/css/normalize.css"; 17 | @import "~@ionic/angular/css/structure.css"; 18 | @import "~@ionic/angular/css/typography.css"; 19 | @import '~@ionic/angular/css/display.css'; 20 | 21 | /* Optional CSS utils that can be commented out */ 22 | @import "~@ionic/angular/css/padding.css"; 23 | @import "~@ionic/angular/css/float-elements.css"; 24 | @import "~@ionic/angular/css/text-alignment.css"; 25 | @import "~@ionic/angular/css/text-transformation.css"; 26 | @import "~@ionic/angular/css/flex-utils.css"; 27 | -------------------------------------------------------------------------------- /src/app/address/search-address/search-address.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../../style/mixin.scss"; 2 | ion-content { 3 | background-color: #fff; 4 | } 5 | .search_address_page{ 6 | overflow-y: auto; 7 | } 8 | .search_form{ 9 | display: flex; 10 | padding: 1.16rem; 11 | input{ 12 | @include sc(1.1rem, #999); 13 | flex: 4; 14 | background-color: #f1f1f1; 15 | margin-right: 1rem; 16 | height: 2.5rem; 17 | border-radius: 0.25rem; 18 | padding: 0 .67rem; 19 | } 20 | button{ 21 | flex: 1; 22 | @include sc(1.1rem, #fff); 23 | background-color: $blue; 24 | border-radius: 0.25rem; 25 | } 26 | } 27 | .address_list{ 28 | padding: 1.16rem; 29 | li{ 30 | padding: 1.16rem 0; 31 | border-bottom: 0.041rem solid #f5f5f5; 32 | line-height: 1.6rem; 33 | h4{ 34 | @include sc(1.25rem, #555); 35 | } 36 | p{ 37 | @include sc(1.1rem, #999); 38 | } 39 | } 40 | } 41 | .empty_tips{ 42 | @include center; 43 | width: 100%; 44 | p{ 45 | @include sc(0.83rem, #aaa); 46 | line-height: 1.16rem; 47 | text-align: center; 48 | 49 | } 50 | } -------------------------------------------------------------------------------- /src/app/confirm-order/remark/remark.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 |
8 |
快速备注
9 |
    10 |
  • 11 | {{remarkTtem}} 13 |
  • 14 |
15 |
16 |
17 |
其他备注
18 | 19 |
20 |
确定
21 |
22 | 23 |
24 |
-------------------------------------------------------------------------------- /src/app/shop/detail/shop-detail.page.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { ShopService } from '../../service'; 3 | import { ImgBaseUrl } from '../../config/env'; 4 | 5 | @Component({ 6 | selector: 'page-shop-detail', 7 | templateUrl: 'shop-detail.page.html', 8 | styleUrls: ['shop-detail.page.scss'] 9 | }) 10 | export class ShopDetailPage { 11 | shopDetailData: any; 12 | ratingScoresData: any; 13 | rating: any; 14 | imgBaseUrl: string = ImgBaseUrl; 15 | ratingParams: any; 16 | constructor(public shopService: ShopService) { 17 | this.shopDetailData = this.shopService.shopDetailData; 18 | this.ratingScoresData = this.shopService.ratingScoresData; 19 | this.rating = this.shopService.ratingList[0]; 20 | this.ratingParams = {rating: this.shopDetailData.rating, title: this.shopDetailData.name}; 21 | } 22 | 23 | getImgPath(path) { 24 | let suffix; 25 | if (!path) { 26 | return 'http://test.fe.ptdev.cn/elm/elmlogo.jpeg'; 27 | } 28 | if (path.indexOf('jpeg') !== -1) { 29 | suffix = '.jpeg'; 30 | } else { 31 | suffix = '.png'; 32 | } 33 | const url = '/' + path.substr(0, 1) + '/' + path.substr(1, 2) + '/' + path.substr(3) + suffix; 34 | return 'https://fuss10.elemecdn.com' + url; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/style/common.scss: -------------------------------------------------------------------------------- 1 | a, article, aside, b, body, button, dd, div, dl, dt, figcaption, figure, footer, h1, h2, h3, h4, h5, h6, header, i, input, li, nav, p, section, select, span, textarea, ul { 2 | padding: 0; 3 | margin: 0; 4 | list-style: none; 5 | font-style: normal; 6 | text-decoration: none; 7 | border: none; 8 | outline: none; 9 | font-weight: 400; 10 | font-family: Microsoft Yahei; 11 | box-sizing: border-box; 12 | -webkit-tap-highlight-color: transparent; 13 | -webkit-font-smoothing: antialiased; 14 | } 15 | 16 | html { 17 | font-size: 14px; 18 | } 19 | 20 | .clear:after { 21 | content: ''; 22 | display: block; 23 | clear: both; 24 | } 25 | 26 | @keyframes backOpacity{ 27 | 0% { opacity: 1 } 28 | 25% { opacity: .5 } 29 | 50% { opacity: 1 } 30 | 75% { opacity: .5 } 31 | 100% { opacity: 1 } 32 | } 33 | 34 | .animation_opactiy{ 35 | animation: backOpacity 2s ease-in-out infinite; 36 | } 37 | 38 | input:-webkit-autofill, 39 | input:-webkit-autofill:hover, 40 | input:-webkit-autofill:focus { 41 | box-shadow:0 0 0 60px #fff inset !important; 42 | -webkit-text-fill-color: #666 !important; 43 | } 44 | 45 | .ellipsis { 46 | overflow: hidden; 47 | text-overflow: ellipsis; 48 | white-space: nowrap; 49 | } -------------------------------------------------------------------------------- /src/app/msite/msite.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../style/mixin.scss"; 2 | @import "../../style/common.scss"; 3 | ion-icon { 4 | font-size: 2rem; 5 | vertical-align: middle; 6 | } 7 | .msite_nav{ 8 | background-color: #fff; 9 | border-bottom: .041rem solid $bc; 10 | height: 15.6rem; 11 | .swiper-container{ 12 | @include wh(100%, 100%); 13 | position: relative; 14 | } 15 | .fl_back{ 16 | @include wh(100%, 100%); 17 | } 18 | } 19 | .food_types_container{ 20 | height: 100%; 21 | .swiper-slide { 22 | flex-wrap: wrap; 23 | } 24 | .link_to_food{ 25 | width: 25%; 26 | padding: .5rem 0rem; 27 | @include ifj(center); 28 | figure{ 29 | img{ 30 | margin-bottom: .83rem; 31 | @include wh(3rem, 3rem); 32 | } 33 | figcaption{ 34 | text-align: center; 35 | @include sc(.37rem, #666); 36 | } 37 | } 38 | } 39 | } 40 | .shop_list_container{ 41 | margin-top: .668rem; 42 | border-top: .041rem solid $bc; 43 | background-color: #fff; 44 | .shop_header{ 45 | .shop_icon{ 46 | fill: #999; 47 | margin-left: 1rem; 48 | vertical-align: middle; 49 | @include wh(1rem, 1rem); 50 | } 51 | .shop_header_title{ 52 | color: #999; 53 | @include font(.92rem, 2.7rem); 54 | } 55 | } 56 | } 57 | .empty_data{ 58 | @include sc(0.835rem, #666); 59 | text-align: center; 60 | line-height: 3.34rem; 61 | } -------------------------------------------------------------------------------- /src/app/shared/components/shop/search/shop-search.html: -------------------------------------------------------------------------------- 1 |
  • 2 |
    3 | 4 |
    5 |
    6 |
    7 |

    8 | {{shop.name}} 9 | 10 | 11 | 12 | 支付 13 | 14 |

    15 |

    月售 {{shop.month_sales||shop.recent_order_num}} 单

    16 |

    {{shop.delivery_fee||shop.float_minimum_order_amount}} 元起送 / 距离{{shop.distance}}

    17 |
    18 |
      19 |
    • 20 | {{activity?.icon_name}} 21 | {{activity?.name}} 22 | (手机客户端专享) 23 |
    • 24 |
    25 |
    26 |
  • -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | const routes: Routes = [ 5 | { path: '', redirectTo: 'home', pathMatch: 'full' }, 6 | { path: 'address', loadChildren: () => import('./address/address.module').then(m => m.AddressPageModule) }, 7 | { path: 'tabs', loadChildren: () => import('./tabs/tabs.module').then(m => m.TabsPageModule) }, 8 | { path: 'city/:id', loadChildren: () => import('./city/city.module').then(m => m.CityPageModule) }, 9 | { path: 'confirmOrder', loadChildren: () => import('./confirm-order/confirm-order.module').then(m => m.ConfirmOrderPageModule) }, 10 | { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomePageModule) }, 11 | { path: 'login', loadChildren: () => import('./login/login.module').then(m => m.LoginPageModule) }, 12 | { path: 'food', loadChildren: () => import('./food/food.module').then(m => m.FoodPageModule) }, 13 | { path: 'order/detail', loadChildren: () => import('./order/order-detail/order-detail.module').then(m => m.OrderDetailPageModule) }, 14 | { path: 'shop', loadChildren: () => import('./shop/shop.module').then(m => m.ShopPageModule) } 15 | ]; 16 | @NgModule({ 17 | imports: [RouterModule.forRoot(routes, { useHash: true })], 18 | exports: [RouterModule] 19 | }) 20 | export class AppRoutingModule { } 21 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 4 | import { RouteReuseStrategy } from '@angular/router'; 5 | 6 | import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; 7 | import { SplashScreen } from '@ionic-native/splash-screen/ngx'; 8 | import { StatusBar } from '@ionic-native/status-bar/ngx'; 9 | 10 | import { AppRoutingModule } from './app-routing.module'; 11 | import { AppComponent } from './app.component'; 12 | 13 | import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; 14 | 15 | import { SharedModule } from './shared'; 16 | import { CoreModule } from './core'; 17 | import { ConvertRequestService } from './service/convert-request.service'; 18 | 19 | @NgModule({ 20 | declarations: [AppComponent], 21 | entryComponents: [], 22 | imports: [ 23 | BrowserModule, 24 | BrowserAnimationsModule, 25 | IonicModule.forRoot(), 26 | AppRoutingModule, 27 | HttpClientModule, 28 | SharedModule, 29 | CoreModule 30 | ], 31 | providers: [ 32 | StatusBar, 33 | SplashScreen, 34 | { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, 35 | { provide: HTTP_INTERCEPTORS, useClass: ConvertRequestService, multi: true }, 36 | ], 37 | bootstrap: [AppComponent] 38 | }) 39 | export class AppModule { } 40 | -------------------------------------------------------------------------------- /src/app/search/search.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
    7 | 8 | 提交 9 |
    10 |
    11 |

    商家

    12 | 13 |
    14 |
    15 |

    搜索历史

    16 |
      17 |
    • 18 | {{item}} 19 | 20 | 21 | 22 | 23 |
    • 24 |
    25 |
    清空搜索历史
    26 |
    27 |
    很抱歉!无搜索结果
    28 |
    -------------------------------------------------------------------------------- /src/app/home/home.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 21 |
    22 |

    热门城市

    23 |
      24 |
    • 25 | {{hotCity?.name}} 26 |
    • 27 |
    28 |
    29 |
    30 |
      31 |
    • 32 |

      {{group?.letter}}(按字母排序)

      33 |
        34 |
      • {{city?.name}}
      • 35 |
      36 |
    • 37 |
    38 |
    39 |
    -------------------------------------------------------------------------------- /src/app/home/home.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { DataService } from '../service'; 3 | 4 | @Component({ 5 | selector: 'page-home', 6 | templateUrl: 'home.page.html', 7 | styleUrls: ['home.page.scss'] 8 | }) 9 | 10 | export class HomePage implements OnInit { 11 | guessCity: string; 12 | guessCityId: string; 13 | hotCities: any[]; 14 | groupCities: any; 15 | constructor(public dataService: DataService) { 16 | this.guessCity = ''; 17 | this.hotCities = []; 18 | } 19 | 20 | ngOnInit() { 21 | this.getCurrentCity(); 22 | this.getHotCity(); 23 | this.getGroupCity(); 24 | } 25 | 26 | getCurrentCity() { 27 | this.dataService.getGuessCity().subscribe(res => { 28 | this.guessCity = res.name; 29 | this.guessCityId = res.id; 30 | }, err => { 31 | this.guessCity = '无数据'; 32 | this.guessCityId = ''; 33 | }); 34 | } 35 | 36 | getHotCity() { 37 | this.dataService.getHotCity().subscribe(res => { 38 | if (Array.isArray(res)) { 39 | this.hotCities = res.map((city) => { 40 | return { name: city.name, id: city.id }; 41 | }); 42 | } 43 | }, err => { 44 | this.hotCities = []; 45 | }); 46 | } 47 | 48 | getGroupCity() { 49 | this.dataService.getGroupCity().subscribe(res => { 50 | this.groupCities = res; 51 | }, err => { 52 | this.groupCities = []; 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/assets/imgs/fl.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/style/ionic.scss: -------------------------------------------------------------------------------- 1 | /** ion-toolbar **/ 2 | ion-toolbar { 3 | min-height: 3.3rem; 4 | --background: #108ee9; 5 | --border-color: #108ee9; 6 | } 7 | 8 | /** ion-title **/ 9 | ion-title { 10 | text-align: center; 11 | font-size: 1.4rem; 12 | } 13 | 14 | /** ion-back-button **/ 15 | .back-button-native { 16 | font-size: 1.2rem !important; 17 | } 18 | ion-back-button { 19 | position: absolute; 20 | } 21 | .back-button-native[data-ion-back-button-md] { 22 | margin-left: -1rem; 23 | } 24 | 25 | /** ion-content **/ 26 | ion-content { 27 | background-color: #f5f5f5; 28 | } 29 | 30 | /** toast **/ 31 | ion-toast { 32 | --background: rgba(58, 58, 58, 0.9); 33 | --color: #fff; 34 | text-align: center; 35 | } 36 | 37 | .toast-container { 38 | text-align: center; 39 | background-color: #333; 40 | border-radius: .2rem; 41 | } 42 | 43 | .toast-ios .toast-wrapper, 44 | .toast-md .toast-wrapper { 45 | left: 1rem; 46 | right: 1rem; 47 | border-radius: 0.65rem; 48 | width: auto; 49 | } 50 | 51 | .toast-ios .toast-message, 52 | .toast-md .toast-message { 53 | font-size: 1rem; 54 | color: #fff; 55 | padding: .6rem; 56 | } 57 | 58 | /** infinite sroll **/ 59 | ion-infinite-scroll-content { 60 | min-height: 1px; 61 | } 62 | 63 | .infinite-loading { 64 | margin-bottom: 0; 65 | } 66 | 67 | /** ion header **/ 68 | .header-md back-icon { 69 | position: absolute; 70 | } 71 | 72 | /** ion slides **/ 73 | .swiper-pagination-bullet { 74 | opacity: 1; 75 | } -------------------------------------------------------------------------------- /src/app/login/login.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 28 | 31 | 34 | 35 | 38 | -------------------------------------------------------------------------------- /src/app/order/order-detail/order-detail.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { AppService, DataService, LocalStorageService } from '../../service'; 4 | import { ImgBaseUrl } from '../../config/env'; 5 | import { UserInfo } from '../../class'; 6 | 7 | @Component({ 8 | selector: 'page-order-detail', 9 | templateUrl: 'order-detail.page.html', 10 | styleUrls: ['order-detail.page.scss'] 11 | }) 12 | export class OrderDetailPage extends UserInfo implements OnInit { 13 | orderData: any; 14 | orderDetail: any; 15 | showLoading: boolean = true; 16 | imgBaseUrl: string = ImgBaseUrl; 17 | shopId: string; 18 | params: {geohash: string}; 19 | constructor(public router: Router, 20 | public appService: AppService, 21 | public dataService: DataService, 22 | public localStorageService: LocalStorageService) { 23 | super(appService, localStorageService); 24 | } 25 | 26 | ngOnInit() { 27 | this.shopId = this.appService.orderDetail.restaurant_id; 28 | this.params = { geohash: this.appService.geohash }; 29 | this.orderDetail = this.appService.orderDetail; 30 | if (this.userId && this.appService.orderDetail) { 31 | this.dataService.getOrderDetail(this.userId, this.appService.orderDetail.unique_id).subscribe(res => { 32 | this.orderData = res; 33 | this.showLoading = false; 34 | }); 35 | } else { 36 | this.router.navigate(['/login']); 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/app/confirm-order/remark/remark.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { AppService, DataService, LocalStorageService } from '../../service'; 4 | 5 | @Component({ 6 | selector: 'page-remark', 7 | templateUrl: 'remark.page.html', 8 | styleUrls: ['remark.page.scss'] 9 | }) 10 | export class RemarkPage implements OnInit { 11 | showLoading: boolean = true; 12 | remarkList: any; 13 | remarkText: any = {}; 14 | inputText: string = ''; 15 | id: string; 16 | sig: any; 17 | constructor( 18 | public route: ActivatedRoute, 19 | public router: Router, 20 | public localStorageService: LocalStorageService, 21 | public appService: AppService, 22 | public dataService: DataService) { 23 | this.id = this.route.snapshot.queryParamMap.get('id'); 24 | this.sig = this.route.snapshot.queryParamMap.get('sig'); 25 | } 26 | 27 | ngOnInit() { 28 | this.remarkList = this.dataService.getRemark(this.id, this.sig).subscribe(res => { 29 | this.remarkList = res; 30 | this.showLoading = false; 31 | }); 32 | } 33 | 34 | chooseRemark(index: number, remarkIndex: string, text: string) { 35 | this.remarkText[index] = [remarkIndex, text]; 36 | this.remarkText = Object.assign({}, this.remarkText); 37 | } 38 | 39 | confirmRemark() { 40 | this.appService.confirmRemark = { remarkText: this.remarkText, inputText: this.inputText }; 41 | window.history.back(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/app/shared/components/buy-cart/buy-cart.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 5 | 6 | 7 | 8 | 9 | {{foodNum()}} 10 | 11 | 12 | 13 |
    14 |
    15 |
    16 | 17 | 18 | 19 | {{foodNum()}} 20 | 选规格 21 |
    22 |
    23 |
    -------------------------------------------------------------------------------- /src/style/mixin.scss: -------------------------------------------------------------------------------- 1 | $blue: #3190e8; 2 | $bc: #e4e4e4; 3 | $fc:#fff; 4 | 5 | // 背景图片地址和大小 6 | @mixin bis($url) { 7 | background-image: url($url); 8 | background-repeat: no-repeat; 9 | background-size: 100% 100%; 10 | } 11 | 12 | @mixin borderRadius($radius) { 13 | -webkit-border-radius: $radius; 14 | -moz-border-radius: $radius; 15 | -ms-border-radius: $radius; 16 | -o-border-radius: $radius; 17 | border-radius: $radius; 18 | } 19 | // 定位全屏 20 | @mixin allcover{ 21 | position:absolute; 22 | top:0; 23 | right:0; 24 | } 25 | 26 | // 定位上下左右居中 27 | @mixin center { 28 | position: absolute; 29 | top: 50%; 30 | left: 50%; 31 | transform: translate(-50%, -50%); 32 | } 33 | 34 | // 定位上下居中 35 | @mixin ct { 36 | position: absolute; 37 | top: 50%; 38 | transform: translateY(-50%); 39 | } 40 | 41 | // 定位上下居中 42 | @mixin cl { 43 | position: absolute; 44 | left: 50%; 45 | transform: translateX(-50%); 46 | } 47 | 48 | // 宽高 49 | @mixin wh($width, $height){ 50 | width: $width; 51 | height: $height; 52 | } 53 | 54 | // 字体大小、行高、字体 55 | @mixin font($size, $line-height, $family: 'Microsoft YaHei') { 56 | font: #{$size}/#{$line-height} $family; 57 | } 58 | 59 | // 字体大小,颜色 60 | @mixin sc($size, $color){ 61 | font-size: $size; 62 | color: $color; 63 | } 64 | 65 | // flex 布局和 子元素 对其方式 66 | @mixin fj($type: space-between){ 67 | display: flex; 68 | justify-content: $type; 69 | 70 | } 71 | 72 | // inline-flex 布局和 子元素 对其方式 73 | @mixin ifj($type: space-between){ 74 | display: inline-flex; 75 | justify-content: $type; 76 | 77 | } -------------------------------------------------------------------------------- /src/app/login/login.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../style/mixin.scss"; 2 | 3 | ion-toggle { 4 | position: absolute; 5 | top: .3rem; 6 | right: 1rem; 7 | } 8 | ion-button { 9 | font-size: 1.2rem; 10 | } 11 | .login_content { 12 | padding-top: 1rem; 13 | } 14 | .login_form { 15 | background-color: #fff; 16 | .input_container{ 17 | display: flex; 18 | justify-content: space-between; 19 | padding: 1rem 1.33rem; 20 | border-bottom: 1px solid #f1f1f1; 21 | input{ 22 | @include sc(1.16rem, #666); 23 | outline: none; 24 | } 25 | } 26 | .input_pwd { 27 | position: relative; 28 | } 29 | .captcha_code_container{ 30 | height: 3.6rem; 31 | .img_change_img{ 32 | display: flex; 33 | align-items: center; 34 | margin-right: 1rem; 35 | img{ 36 | @include wh(5.8rem, 2.5rem); 37 | margin-right: .34rem; 38 | } 39 | .change_img{ 40 | display: flex; 41 | flex-direction: 'column'; 42 | flex-wrap: wrap; 43 | width: 3.34rem; 44 | justify-content: center; 45 | p{ 46 | @include sc(.92rem, #666); 47 | } 48 | p:nth-of-type(2){ 49 | color: #3b95e9; 50 | margin-top: .34rem; 51 | } 52 | } 53 | } 54 | } 55 | } 56 | .login_tips{ 57 | @include sc(.8rem, red); 58 | padding: .7rem 1rem; 59 | line-height: .8rem; 60 | } 61 | .button_login { 62 | text-align: center; 63 | margin: 1rem; 64 | span { 65 | color: #fff; 66 | } 67 | } 68 | .show_pwd { 69 | display: none; 70 | } 71 | -------------------------------------------------------------------------------- /src/app/shared/components/shop/search/shop-search.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../../style/mixin.scss"; 2 | .list_li{ 3 | display: flex; 4 | justify-content: 'center'; 5 | padding: 0.835rem; 6 | border-bottom: 0.041rem solid $bc; 7 | .shop_left{ 8 | margin-right: 0.41rem; 9 | .restaurant_img{ 10 | @include wh(2.839rem, 2.839rem); 11 | } 12 | } 13 | .shop_right{ 14 | font-size: 0.92rem; 15 | flex: 1; 16 | .shop_right_text{ 17 | padding-bottom: 0.41rem; 18 | border-bottom: 0.041rem solid $bc; 19 | p{ 20 | line-height: 1.502rem; 21 | } 22 | .pay_icon{ 23 | margin-bottom: -0.13rem; 24 | } 25 | } 26 | .shop_right_detail{ 27 | margin-top: 0.41rem; 28 | li{ 29 | font-size: 0; 30 | span{ 31 | font-size: .835rem; 32 | vertical-align: middle; 33 | display: inline-block; 34 | margin-bottom: 0.134rem; 35 | } 36 | .activity_icon{ 37 | @include sc(.835rem, #fff); 38 | font-weight: bold; 39 | padding: .067rem; 40 | border-radius: 0.25rem; 41 | margin-right: 0.21rem; 42 | } 43 | .only_phone{ 44 | color: #FF6000; 45 | } 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/assets/icon/mine.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/profile/profile.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnDestroy, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { AppService, DataService, LocalStorageService } from '../service'; 4 | import { UserInfo } from '../class'; 5 | import { ImgBaseUrl } from '../config/env'; 6 | 7 | @Component({ 8 | selector: 'page-profile', 9 | templateUrl: 'profile.page.html', 10 | styleUrls: ['profile.page.scss'] 11 | }) 12 | export class ProfilePage extends UserInfo implements OnDestroy, OnInit { 13 | userId: string; 14 | userInfo: any; 15 | mobile: string; 16 | imgBaseUrl: string = ImgBaseUrl; 17 | 18 | constructor(public appService: AppService, 19 | public dataService: DataService, 20 | public localStorageService: LocalStorageService, 21 | public router: Router) { 22 | super(appService, localStorageService); 23 | } 24 | 25 | ngOnInit() { 26 | this.userId = this.localStorageService.getStore('userId'); 27 | if (this.userId) { 28 | this.getUserInfo(this.userId); 29 | } else { 30 | this.mobile = '暂无绑定手机号'; 31 | } 32 | } 33 | 34 | public getUserInfo(userId: string) { 35 | this.dataService.getUserInfo(userId).subscribe(res => { 36 | this.userInfo = res; 37 | this.mobile = this.userInfo.mobile || '暂无绑定手机号'; 38 | }); 39 | } 40 | 41 | public exit() { 42 | this.localStorageService.removeStore('userId'); 43 | this.userInfo = {}; 44 | this.appService.userInfoEvent.emit('update'); 45 | } 46 | 47 | public toOrderPage() { 48 | this.router.navigateByUrl('/tabs/order'); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/app/shared/components/components.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { IonicModule } from '@ionic/angular'; 5 | import { RouterModule } from '@angular/router'; 6 | 7 | import { BackHeaderComponent } from './back/back-header'; 8 | import { BackIconComponent } from './back/back-icon'; 9 | import { BuyCartComponent } from './buy-cart/buy-cart'; 10 | import { ElmSvgComponent } from './svg/svg'; 11 | import { LoginHeaderComponent } from './login-header/login-header'; 12 | import { LoadingComponent } from './loading/loading'; 13 | import { RatingStarComponent } from './rating-star/rating-star'; 14 | import { ShoplistComponent } from './shop/list/shop-list'; 15 | import { ShopSearchComponent } from './shop/search/shop-search'; 16 | import { ShopMsiteComponent } from './shop/msite/shop-msite'; 17 | import { ShopEvaluateComponent } from './shop/evaluate/evaluate'; 18 | 19 | // import { DirectivesModule } from '../directives'; 20 | const coms: any[] = [ 21 | BackHeaderComponent, 22 | BackIconComponent, 23 | BuyCartComponent, 24 | ElmSvgComponent, 25 | LoginHeaderComponent, 26 | LoadingComponent, 27 | RatingStarComponent, 28 | ShoplistComponent, 29 | ShopSearchComponent, 30 | ShopMsiteComponent, 31 | ShopEvaluateComponent 32 | ]; 33 | 34 | @NgModule({ 35 | imports: [ 36 | CommonModule, 37 | FormsModule, 38 | RouterModule, 39 | IonicModule.forRoot(), 40 | ], 41 | declarations: [ 42 | coms 43 | ], 44 | exports: [ 45 | coms 46 | ], 47 | entryComponents: [], 48 | }) 49 | export class ComponentsModule { } 50 | -------------------------------------------------------------------------------- /src/app/search/search.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../style/mixin.scss"; 2 | @import "../../style/common.scss"; 3 | 4 | .seller_form { 5 | background-color: #fff; 6 | padding: .8rem; 7 | display: flex; 8 | } 9 | 10 | ion-input { 11 | background-color: #f2f2f2; 12 | --padding-start: .5rem; 13 | --padding-end: .5rem; 14 | border: 1px solid #e4e4e4; 15 | color: #333; 16 | font-size: 1.1rem; 17 | height: 2.5rem; 18 | flex: 4; 19 | } 20 | 21 | ion-button { 22 | --border-radius: 3px; 23 | --height:2.5rem; 24 | --margin-top: 0; 25 | --margin-start: 0; 26 | --margin-end: 0; 27 | --margin-bottom: 0; 28 | float: right; 29 | flex:1; 30 | } 31 | 32 | .title_restaurant{ 33 | font-size: 1rem; 34 | line-height: 3.3rem; 35 | text-indent: 0.835rem; 36 | font-weight: bold; 37 | color: #666; 38 | } 39 | .list_container{ 40 | background-color: #fff; 41 | } 42 | .search_history{ 43 | .history_list{ 44 | background-color: #fff; 45 | border-bottom: 0.041rem solid $bc; 46 | @include font(1.16rem, 3.34rem); 47 | padding: 0 0.5rem; 48 | display: flex; 49 | justify-content: space-between; 50 | align-items: center; 51 | .history_text{ 52 | display: inline-block; 53 | width: 80%; 54 | } 55 | .delete_icon{ 56 | @include wh(1.67rem, 1.67rem); 57 | } 58 | } 59 | .clear_history{ 60 | background-color: #fff; 61 | color: $blue; 62 | @include font(1.169rem, 3.34rem); 63 | font-weight: bold; 64 | text-align: center; 65 | } 66 | } 67 | .search_none{ 68 | margin: 0 auto; 69 | @include font(1.1rem, 2.9rem); 70 | color: #333; 71 | background-color: #fff; 72 | text-align: center; 73 | margin-top: 0.21rem; 74 | } -------------------------------------------------------------------------------- /src/app/city/city.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../style/mixin.scss"; 2 | @import "../../style/common.scss"; 3 | 4 | ion-input { 5 | background-color: #fff; 6 | --padding-start: .5rem; 7 | --padding-end: .5rem; 8 | border: 1px solid #e4e4e4; 9 | color: #333; 10 | font-size: 1.1rem; 11 | height: 2.34rem; 12 | } 13 | 14 | .change_city { 15 | font-size: 1rem; 16 | position: absolute; 17 | top: 0; 18 | bottom: 0; 19 | right: .6rem; 20 | margin: auto 0; 21 | height: 1.4rem; 22 | } 23 | 24 | .city_form { 25 | background-color: #fff; 26 | border-top: 1px solid #e4e4e4; 27 | border-bottom: 1px solid #e4e4e4; 28 | padding-top: .65rem; 29 | .city_search { 30 | margin: 0 auto .65rem auto; 31 | width: 90%; 32 | } 33 | } 34 | 35 | .button_submit { 36 | width: 100%; 37 | padding: 0 1.28rem .669rem 1.28rem; 38 | background-color: #fff; 39 | border-bottom: 1px solid #e4e4e4; 40 | } 41 | .getpois_ul { 42 | background-color: #fff; 43 | border-top: 1px solid #e4e4e4; 44 | li { 45 | padding-top: 1.088rem; 46 | padding-bottom: .92rem; 47 | border-bottom: 1px solid #e4e4e4; 48 | .pois_name { 49 | font-size: 1.088rem; 50 | width: 90%; 51 | margin: 0 auto .586rem; 52 | } 53 | .pois_address { 54 | font-size: .857rem; 55 | width: 90%; 56 | margin: 0 auto; 57 | color: #999; 58 | } 59 | } 60 | } 61 | .pois_search_history { 62 | font-size: .8rem; 63 | padding-left: .8rem; 64 | 65 | } 66 | .search_none_place, .clear_all_history { 67 | line-height: 3rem; 68 | font-size: 1.1rem; 69 | background-color: #fff; 70 | } 71 | .search_none_place { 72 | text-indent: .85rem; 73 | } 74 | .clear_all_history { 75 | text-align: center; 76 | } 77 | -------------------------------------------------------------------------------- /src/app/confirm-order/remark/remark.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../../style/mixin.scss"; 2 | .header_style{ 3 | @include sc(1.1rem, #333); 4 | line-height: 3.3rem; 5 | } 6 | .quick_remark{ 7 | background-color: #fff; 8 | margin-top: .67rem; 9 | padding: 0 1rem 1.67rem; 10 | ul{ 11 | display: flex; 12 | flex-wrap: wrap; 13 | li{ 14 | margin-right: 1rem; 15 | margin-bottom: 2rem; 16 | span{ 17 | @include sc(1rem, #333); 18 | padding: .5rem 1rem; 19 | border: 0.061rem solid #3190e8; 20 | border-left: 0; 21 | } 22 | .first{ 23 | border-left: 0.061em solid #3190e8; 24 | border-top-left-radius: .33rem; 25 | border-bottom-left-radius: .33rem; 26 | } 27 | .last{ 28 | border-top-right-radius: .33rem; 29 | border-bottom-right-radius: .33rem; 30 | } 31 | .choosed{ 32 | color: #fff; 33 | background-color: #3190e8; 34 | } 35 | } 36 | } 37 | } 38 | .input_remark{ 39 | background-color: #fff; 40 | .input_text{ 41 | width: 100%; 42 | background-color: #f9f9f9; 43 | border: 0.041rem solid #eee; 44 | resize: none; 45 | min-height: 7.5rem; 46 | border-radius: .33rem; 47 | @include sc(1rem, #666); 48 | padding: .83rem; 49 | } 50 | } 51 | .determine{ 52 | background-color: #4cd964; 53 | @include sc(1.16rem, #fff); 54 | text-align: center; 55 | margin: 0 1.16rem; 56 | line-height: 3rem; 57 | border-radius: 0.33rem; 58 | } -------------------------------------------------------------------------------- /src/app/confirm-order/payment/payment.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
    6 |
    7 |
    支付剩余时间
    8 |

    {{countNum | timeLast}}

    9 |
    10 | 详情 11 | ¥ {{cartPrice&&cartPrice.toFixed(2) || payDetail.resultData.orderInfo.orderAmount&&(payDetail.resultData.orderInfo.orderAmount/100).toFixed(2)}} 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 |
    -------------------------------------------------------------------------------- /src/app/shared/components/buy-cart/buy-cart.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../style/mixin.scss"; 2 | .cart_module{ 3 | .add_icon{ 4 | position: relative; 5 | // z-index: 999; 6 | } 7 | .cart_button{ 8 | display: flex; 9 | align-items: center; 10 | } 11 | svg{ 12 | @include wh(1.5rem, 1.5rem); 13 | fill: #3190e8; 14 | } 15 | .cart_num{ 16 | @include sc(1.1rem, #666); 17 | min-width: 1rem; 18 | text-align: center; 19 | font-family: Helvetica Neue,Tahoma; 20 | margin-right: .2rem; 21 | } 22 | .choose_specification{ 23 | .choose_icon_container{ 24 | display: flex; 25 | align-items: center; 26 | .show_chooselist{ 27 | display: block; 28 | @include sc(.92rem, #fff); 29 | padding: .16rem .33rem; 30 | background-color: $blue; 31 | border-radius: 0.33rem; 32 | border: 1px solid $blue; 33 | } 34 | } 35 | } 36 | } 37 | .showReduce-enter-active, .showReduce-leave-active { 38 | transition: all .3s ease-out; 39 | } 40 | .showReduce-enter, .showReduce-leave-active { 41 | opacity: 0; 42 | transform: translateX(1rem); 43 | } 44 | .fade-enter-active, .fade-leave-active { 45 | transition: all .3s; 46 | } 47 | .fade-enter, .fade-leave-active { 48 | opacity: 0; 49 | } 50 | .fadeBounce-enter-active, .fadeBounce-leave-active { 51 | transition: all .3s; 52 | } 53 | .fadeBounce-enter, .fadeBounce-leave-active { 54 | opacity: 0; 55 | transform: scale(.7); 56 | } -------------------------------------------------------------------------------- /src/app/msite/msite.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{addressTitle}} 5 | 6 | 7 | 8 | 9 | 26 |
    27 |
    28 | 29 | 30 | 31 | 附近商家 32 |
    33 | 34 |

    没有更多了

    35 | 36 |
    37 | 38 | 39 | 40 |
    -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "myapp", 3 | "version": "0.0.1", 4 | "author": "nuonuoge", 5 | "homepage": "https://github.com/nuonuoge/ionic4_angular6_elm", 6 | "scripts": { 7 | "ng": "ng", 8 | "start": "ng serve --port 5555", 9 | "build": "ng build --prod --aot", 10 | "test": "ng test", 11 | "lint": "ng lint", 12 | "e2e": "ng e2e" 13 | }, 14 | "private": true, 15 | "dependencies": { 16 | "@angular/animations": "~10.0.0", 17 | "@angular/common": "~10.0.0", 18 | "@angular/core": "~10.0.0", 19 | "@angular/forms": "~10.0.0", 20 | "@angular/platform-browser": "~10.0.0", 21 | "@angular/platform-browser-dynamic": "~10.0.0", 22 | "@angular/router": "~10.0.0", 23 | "@ionic-native/core": "^5.0.0", 24 | "@ionic-native/splash-screen": "^5.0.0", 25 | "@ionic-native/status-bar": "^5.0.0", 26 | "@ionic/angular": "^5.0.0", 27 | "rxjs": "~6.5.5", 28 | "tslib": "^2.0.0", 29 | "zone.js": "~0.10.3" 30 | }, 31 | "devDependencies": { 32 | "@angular-devkit/build-angular": "~0.1000.0", 33 | "@angular/cli": "~10.0.5", 34 | "@angular/compiler": "~10.0.0", 35 | "@angular/compiler-cli": "~10.0.0", 36 | "@angular/language-service": "~10.0.0", 37 | "@ionic/angular-toolkit": "^2.3.0", 38 | "@types/node": "^12.11.1", 39 | "@types/jasmine": "~3.5.0", 40 | "@types/jasminewd2": "~2.0.3", 41 | "codelyzer": "^6.0.0", 42 | "jasmine-core": "~3.5.0", 43 | "jasmine-spec-reporter": "~5.0.0", 44 | "karma": "~5.0.0", 45 | "karma-chrome-launcher": "~3.1.0", 46 | "karma-coverage-istanbul-reporter": "~3.0.2", 47 | "karma-jasmine": "~3.3.0", 48 | "karma-jasmine-html-reporter": "^1.5.0", 49 | "protractor": "~7.0.0", 50 | "ts-node": "~8.3.0", 51 | "tslint": "~6.1.0", 52 | "typescript": "~3.9.5" 53 | }, 54 | "description": "An Ionic project" 55 | } 56 | -------------------------------------------------------------------------------- /src/app/shared/components/shop/msite/shop-msite.html: -------------------------------------------------------------------------------- 1 |
  • 2 |
    3 | 4 |
    5 |
    6 |
    7 |

    {{shop.name}}

    8 |
      9 |
    • {{shop.icon_name}}
    • 10 |
    11 |
    12 |
    13 |
    14 |
    15 | 16 | {{shop.rating}} 17 |
    18 |
    19 | 月售{{shop.recent_order_num}}单 20 |
    21 |
    22 |
    23 | {{shop.delivery_mode.text}} 24 | 准时达 25 |
    26 |
    27 |
    28 |

    29 | ¥{{shop.float_minimum_order_amount}}起送 30 | / {{shop.piecewise_agent_fee.tips}} 31 |

    32 |

    33 | {{shop.distance > 1000? (shop.distance/1000).toFixed(2) + 'km': shop.distance + 'm'}} 34 | / 35 | 36 | {{shop.distance}} 37 | / 38 | {{shop.order_lead_time}} 39 |

    40 |
    41 |
    42 |
  • -------------------------------------------------------------------------------- /src/app/address/address.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../style/mixin.scss"; 2 | .scroll_container{ 3 | height: calc(100% - 4.1rem); 4 | overflow-y: auto; 5 | } 6 | .list_cotainer { 7 | padding-bottom: 10px; 8 | } 9 | .deliverable_address{ 10 | background-color: #fff; 11 | li{ 12 | display: flex; 13 | align-items: center; 14 | border-bottom: 0.041rem solid #f5f5f5; 15 | padding: 1.16rem; 16 | line-height: 1.67rem; 17 | .choosed_address{ 18 | @include wh(1.33rem, 1.33rem); 19 | fill: #4cd964; 20 | margin-right: .67rem; 21 | opacity: 0; 22 | } 23 | .default_address{ 24 | opacity: 1; 25 | } 26 | header{ 27 | @include sc(1.16rem, #333); 28 | span:nth-of-type(1){ 29 | font-size: 1.33rem; 30 | font-weight: bold; 31 | } 32 | } 33 | .address_detail{ 34 | width: 100%; 35 | display: flex; 36 | align-items: center; 37 | span{ 38 | font-size: .83rem; 39 | line-height: 1.1rem; 40 | padding: .15rem; 41 | margin-right: .5rem; 42 | border: 0.05rem solid; 43 | } 44 | p{ 45 | @include sc(1rem, #777); 46 | } 47 | } 48 | } 49 | } 50 | #out_delivery{ 51 | .out_header{ 52 | @include sc(1rem, #666); 53 | line-height: 2.5rem; 54 | padding-left: .83rem; 55 | background-color: #f5f5f5; 56 | } 57 | *{ 58 | color: #ccc; 59 | } 60 | } 61 | .add_icon_footer{ 62 | height: 4.1rem; 63 | border-top: 1px solid f5f5f5; 64 | background-color: #fff; 65 | display: flex; 66 | justify-content: center; 67 | align-items: center; 68 | span{ 69 | @include sc(1.16rem, $blue); 70 | margin-left: .5rem; 71 | } 72 | } -------------------------------------------------------------------------------- /src/app/confirm-order/payment/payment.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { AlertController} from '@ionic/angular'; 4 | import { AppService, CartService, DataService, LocalStorageService } from '../../service'; 5 | 6 | @Component({ 7 | selector: 'page-payment', 8 | templateUrl: 'payment.page.html', 9 | styleUrls: ['payment.page.scss'] 10 | }) 11 | export class PaymentPage implements OnInit { 12 | cartPrice: any; 13 | payDetail: any = {}; 14 | showAlert: boolean = false; 15 | alertText: string = ''; 16 | payWay: number = 1; 17 | countNum: number = 900; // 倒计时15分钟 18 | gotoOrders: boolean = false; 19 | timer: any; 20 | constructor( 21 | public router: Router, 22 | public alertCtrl: AlertController, 23 | public localStorageService: LocalStorageService, 24 | public appService: AppService, 25 | public cartService: CartService, 26 | public dataService: DataService) { 27 | } 28 | 29 | ngOnInit() { 30 | // 清除购物车中当前商铺的信息 31 | if (this.appService.shopId) { 32 | this.cartService.clearCart(this.appService.shopId); 33 | } 34 | this.remainingTime(); 35 | } 36 | 37 | async presentConfirm(message: string) { 38 | const alert = await this.alertCtrl.create({ 39 | header: '确认支付', 40 | message: message, 41 | cssClass: 'confirm', 42 | buttons: [ 43 | { 44 | text: '确认', 45 | handler: () => { 46 | this.router.navigateByUrl('/tabs/order'); 47 | } 48 | } 49 | ] 50 | }); 51 | alert.present(); 52 | } 53 | 54 | // 倒计时 55 | remainingTime() { 56 | clearInterval(this.timer); 57 | this.timer = setInterval(() => { 58 | this.countNum--; 59 | if (this.countNum === 0) { 60 | clearInterval(this.timer); 61 | } 62 | }, 1000); 63 | } 64 | // 确认付款 65 | confirmPay() { 66 | this.presentConfirm('当前环境无法支付,请打开官方APP进行付款?'); 67 | this.gotoOrders = true; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/app/login/login.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Location } from '@angular/common'; 3 | import { ToastController } from '@ionic/angular'; 4 | import { AppService, DataService, LocalStorageService } from '../service'; 5 | 6 | @Component({ 7 | selector: 'page-login', 8 | templateUrl: 'login.page.html', 9 | styleUrls: ['login.page.scss'] 10 | }) 11 | export class LoginPage implements OnInit { 12 | userName: string; 13 | userPwd: string; 14 | showPwd: boolean; 15 | captchaCodeImg: string; 16 | codeNumber: string; 17 | constructor( 18 | public location: Location, 19 | public appService: AppService, 20 | public dataService: DataService, 21 | public storageService: LocalStorageService, 22 | public toastCtrl: ToastController) { 23 | } 24 | 25 | ngOnInit() { 26 | this.userName = ''; 27 | this.userPwd = ''; 28 | this.showPwd = false; 29 | this.getCaptchaCode(); 30 | } 31 | 32 | // 获取验证码 33 | getCaptchaCode() { 34 | this.dataService.getCaptchas().subscribe(res => { 35 | this.captchaCodeImg = res.code; 36 | }); 37 | } 38 | 39 | async toastTip(message: string) { 40 | const toast = await this.toastCtrl.create({ 41 | message, 42 | duration: 2000, 43 | position: 'middle' 44 | }); 45 | toast.present(); 46 | } 47 | 48 | logIn() { 49 | if (!this.userName) { 50 | this.toastTip('请填写用户名'); 51 | return; 52 | } 53 | if (!this.userPwd) { 54 | this.toastTip('请填写密码'); 55 | return; 56 | } 57 | if (!this.codeNumber) { 58 | this.toastTip('请填写验证码'); 59 | return; 60 | } 61 | this.dataService.accountLogin(this.userName, this.userPwd, this.codeNumber).subscribe(res => { 62 | if (!res.user_id) { 63 | this.getCaptchaCode(); 64 | this.toastTip(res.message); 65 | } else { 66 | this.storageService.setStore('userId', res.user_id); 67 | this.appService.userInfoEvent.emit('update'); 68 | this.location.back(); 69 | } 70 | }); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/app/confirm-order/choose-address/choose-address.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../../style/mixin.scss"; 2 | .rating_page{ 3 | height: 100%; 4 | } 5 | .scroll_container{ 6 | height: calc(100% - 4.1rem); 7 | overflow-y: auto; 8 | } 9 | .list_cotainer{ 10 | padding-bottom: 10px; 11 | } 12 | ion-checkbox { 13 | --size: 1.33rem; 14 | } 15 | .deliverable_address{ 16 | background-color: #fff; 17 | li{ 18 | display: flex; 19 | align-items: center; 20 | border-bottom: 0.041rem solid #f5f5f5; 21 | padding: 1.16rem; 22 | line-height: 1.67rem; 23 | .choosed_address{ 24 | @include wh(1.33rem, 1.33rem); 25 | fill: #4cd964; 26 | margin-right: .67rem; 27 | opacity: 0; 28 | } 29 | .default_address{ 30 | opacity: 1; 31 | } 32 | header{ 33 | @include sc(1.16rem, #333); 34 | span:nth-of-type(1){ 35 | font-size: 1.33rem; 36 | font-weight: bold; 37 | } 38 | span + span { 39 | margin-left: .3rem; 40 | } 41 | } 42 | .address_detail{ 43 | width: 100%; 44 | display: flex; 45 | align-items: center; 46 | span{ 47 | font-size: .83rem; 48 | line-height: 1.1rem; 49 | padding: .15rem; 50 | margin-right: .5rem; 51 | border: 0.05rem solid; 52 | } 53 | p{ 54 | @include sc(1rem, #777); 55 | } 56 | } 57 | } 58 | } 59 | #out_delivery{ 60 | .out_header{ 61 | @include sc(1rem, #666); 62 | line-height: 2.5rem; 63 | padding-left: .83rem; 64 | background-color: #f5f5f5; 65 | } 66 | *{ 67 | color: #ccc; 68 | } 69 | } 70 | .add_icon_footer{ 71 | height: 4.1rem; 72 | background-color: #fff; 73 | display: flex; 74 | justify-content: center; 75 | align-items: center; 76 | z-index: 204; 77 | span{ 78 | @include sc(1.16rem, $blue); 79 | margin-left: .5rem; 80 | } 81 | } -------------------------------------------------------------------------------- /src/app/confirm-order/payment/payment.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../../style/mixin.scss"; 2 | .show_time_amount{ 3 | background-color: #fff; 4 | padding: 1.16rem; 5 | text-align: center; 6 | .time_last{ 7 | @include sc(1rem, #666); 8 | margin-top: 1rem; 9 | } 10 | .time{ 11 | @include sc(2.5rem, #333); 12 | margin: .5rem 0 1.67rem; 13 | } 14 | .order_detail{ 15 | @include fj; 16 | span{ 17 | @include sc(1.1rem, #666); 18 | } 19 | span:nth-of-type(2){ 20 | color: #ff6000; 21 | font-weight: bold; 22 | } 23 | } 24 | } 25 | .pay_way{ 26 | background-color: #f1f1f1; 27 | padding: 0 1.16rem; 28 | @include sc(1.16rem, #666); 29 | line-height: 3rem; 30 | } 31 | .pay_way_list{ 32 | background-color: #fff; 33 | .pay_item{ 34 | padding: .67rem 1.16rem; 35 | @include fj; 36 | align-items: center; 37 | line-height: 4.3rem; 38 | border-bottom: 0.041rem solid #f5f5f5; 39 | .pay_icon_contaienr{ 40 | @include fj; 41 | align-items: center; 42 | .zhifubao{ 43 | @include wh(3.3rem, 3.3rem); 44 | background: url(../../../assets/imgs/zhifubao.png) no-repeat; 45 | background-size: 100% 100%; 46 | margin-right: .33rem; 47 | } 48 | svg{ 49 | @include wh(3.3rem, 3.3rem); 50 | margin-right: .5rem; 51 | } 52 | span{ 53 | @include sc(1.16rem, #666); 54 | } 55 | } 56 | .choose_icon{ 57 | @include wh(1.67rem, 1.67rem); 58 | fill: #ccc; 59 | } 60 | .choosed_way{ 61 | fill: #4cd964; 62 | } 63 | } 64 | } 65 | .determine{ 66 | background-color: #4cd964; 67 | @include sc(1.16rem, #fff); 68 | text-align: center; 69 | margin: 0 1.16rem; 70 | line-height: 3rem; 71 | border-radius: 0.33rem; 72 | margin-top: 0.83rem; 73 | font-weight: bold; 74 | } 75 | .confirm { 76 | background-color: #4cd964; 77 | } -------------------------------------------------------------------------------- /src/app/confirm-order/choose-address/choose-address.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { Subscription } from 'rxjs'; 3 | import { AppService, DataService, LocalStorageService, CartService, ShopService } from '../../service'; 4 | import { UserInfo } from '../../class'; 5 | 6 | @Component({ 7 | selector: 'page-choose-address', 8 | templateUrl: 'choose-address.page.html', 9 | styleUrls: ['choose-address.page.scss'] 10 | }) 11 | export class ChooseAddressPage extends UserInfo implements OnInit, OnDestroy { 12 | addressList: any[]; 13 | deliverable: any[]; 14 | deliverdisable: any[]; 15 | iconColor: any = {'公司': '#4cd964', '学校': '#3190e8', '家': '#ff5722'}; 16 | unSub: Subscription; 17 | constructor( 18 | public appService: AppService, 19 | public localStorageService: LocalStorageService, 20 | public cartService: CartService, 21 | public shopService: ShopService, 22 | public dataService: DataService) { 23 | super(appService, localStorageService); 24 | this.unSub = this.appService.notify.subscribe(res => { 25 | this.ngOnInit(); 26 | }); 27 | } 28 | 29 | ngOnInit() { 30 | this.addressList = []; 31 | this.deliverable = []; 32 | this.deliverdisable = []; 33 | if (this.userId) { 34 | this.dataService.getAddressList(this.userId).subscribe(res => { 35 | this.addressList = res; 36 | this.addressList.forEach(item => { 37 | if (item.is_deliverable) { 38 | this.deliverable.push(item); 39 | } else { 40 | this.deliverdisable.push(item); 41 | } 42 | }); 43 | this.setFirstIndex(); 44 | }); 45 | } 46 | } 47 | setFirstIndex() { 48 | if (this.deliverable.length === 1) { 49 | this.appService.choosedAddress = {address: this.deliverable[0], index: 0}; 50 | } 51 | } 52 | defaultIndex() { 53 | if (this.appService.choosedAddress.index) { 54 | return this.appService.choosedAddress.index; 55 | } else { 56 | return 0; 57 | } 58 | } 59 | chooseAddress(address, index) { 60 | this.appService.choosedAddress = {address, index}; 61 | window.history.back(); 62 | } 63 | 64 | ngOndestory() { 65 | if (this.unSub) { 66 | this.unSub.unsubscribe(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/app/home/home.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../style/mixin.scss"; 2 | @import "../../style/common.scss"; 3 | .head_logo { 4 | margin-left: .8rem; 5 | color: #fff; 6 | font-size: 1.2rem; 7 | } 8 | .city_nav { 9 | background-color: #fff; 10 | line-height: 2.75rem; 11 | margin-bottom: .66rem; 12 | .city_tip{ 13 | line-height: 3rem; 14 | display: -webkit-box; 15 | display: -ms-flexbox; 16 | display: flex; 17 | -webkit-box-pack: justify; 18 | -ms-flex-pack: justify; 19 | justify-content: space-between; 20 | padding: 0 .88rem; 21 | } 22 | .city_tip{ 23 | span:first-of-type { 24 | color: #666; 25 | font-size: .9rem; 26 | } 27 | span:nth-of-type(2) { 28 | font-size: 1rem; 29 | font-weight: 900; 30 | font-size: .475rem; 31 | color: #9f9f9f; 32 | } 33 | } 34 | } 35 | .guess_city { 36 | height: 3rem; 37 | display: -webkit-box; 38 | display: -ms-flexbox; 39 | display: flex; 40 | -webkit-box-pack: justify; 41 | -ms-flex-pack: justify; 42 | justify-content: space-between; 43 | -webkit-box-align: center; 44 | -ms-flex-align: center; 45 | align-items: center; 46 | font-size: 1.25rem; 47 | background-color: #fff; 48 | border-top: 1px solid #e4e4e4; 49 | border-bottom: 2px solid #e4e4e4; 50 | padding: 0 .88rem; 51 | span { 52 | color: $blue; 53 | } 54 | .arrow_right { 55 | width: 1rem; 56 | height: 1rem; 57 | fill: #999; 58 | } 59 | } 60 | .hot_city_container { 61 | background-color: #fff; 62 | margin-bottom: .66rem; 63 | } 64 | .citylistul li { 65 | text-align: center; 66 | color: $blue; 67 | border-bottom: .004rem solid #e4e4e4; 68 | border-right: .004rem solid #e4e4e4; 69 | width: 25%; 70 | height: 2.93rem; 71 | line-height: 2.93rem; 72 | font-size: 1rem; 73 | float: left; 74 | } 75 | .city_title { 76 | line-height: 2.57rem; 77 | color: #666; 78 | border-top: 2px solid #e4e4e4; 79 | border-bottom: 1px solid #e4e4e4; 80 | font-size: .92rem; 81 | text-indent: .75rem; 82 | } 83 | .letter_classify_li { 84 | margin-bottom: .66rem; 85 | background-color: #fff; 86 | border-bottom: 1px solid #e4e4e4; 87 | } 88 | .letter_classify_li .groupcity_name_container li { 89 | color: #666; 90 | } 91 | .ellipsis { 92 | overflow: hidden; 93 | text-overflow: ellipsis; 94 | white-space: nowrap; 95 | } 96 | -------------------------------------------------------------------------------- /src/app/shared/components/shop/evaluate/evaluate.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | import { DataService, ShopService } from '../../../../service'; 3 | 4 | @Component({ 5 | selector: 'shop-evaluate', 6 | templateUrl: 'evaluate.html', 7 | styleUrls: ['evaluate.scss'] 8 | }) 9 | export class ShopEvaluateComponent { 10 | @Input() shopId: string; 11 | @Input() rating: string; 12 | ratingList: any; // 评价列表 13 | ratingOffset: number = 0; // 评价获取数据offset值 14 | ratingScoresData: any; // 评价总体分数 15 | showLoading: boolean = false; 16 | items: any[] = []; 17 | touchEnd: boolean = false; 18 | preventRepeatReuqest: boolean = false; // 到达底部加载数据,防止重复加载 19 | constructor(public dataService: DataService, 20 | public shopService: ShopService) { 21 | this.ratingList = this.shopService.ratingList; 22 | this.ratingScoresData = this.shopService.ratingScoresData; 23 | this.shopService.updateData.subscribe(res => { 24 | this.ratingList = this.shopService.ratingList; 25 | this.ratingScoresData = this.shopService.ratingScoresData; 26 | }); 27 | } 28 | loaderMore(event: any) { 29 | if (this.preventRepeatReuqest) { 30 | return; 31 | } 32 | if (this.touchEnd) { 33 | event.target.disabled = true; 34 | return; 35 | } 36 | this.preventRepeatReuqest = true; 37 | this.ratingOffset += 10; 38 | this.showLoading = true; 39 | this.dataService.getRatingList(this.shopId, this.ratingOffset).subscribe(res => { 40 | this.preventRepeatReuqest = false; 41 | if (res.length < 10) { 42 | this.touchEnd = true; 43 | } 44 | event.target.complete(); 45 | this.ratingList = [...this.ratingList, ...res]; 46 | }); 47 | } 48 | 49 | getRatingList(ratingOffset: number, name?: string) { 50 | this.dataService.getRatingList(this.shopId, ratingOffset, name).subscribe(res => { 51 | this.ratingList = this.shopService.ratingList; 52 | }); 53 | } 54 | 55 | getImgPath(path) { 56 | let suffix; 57 | if (!path) { 58 | return 'http://test.fe.ptdev.cn/elm/elmlogo.jpeg'; 59 | } 60 | if (path.indexOf('jpeg') !== -1) { 61 | suffix = '.jpeg'; 62 | } else { 63 | suffix = '.png'; 64 | } 65 | const url = '/' + path.substr(0, 1) + '/' + path.substr(1, 2) + '/' + path.substr(3) + suffix; 66 | return 'https://fuss10.elemecdn.com' + url; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/assets/icon/elm.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/confirm-order/choose-address/choose-address.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
    6 |
    7 |
    8 |
      9 |
    • 10 |
      11 | 12 |
      13 |
      14 |
      15 | {{item.name}} 16 | {{item.sex == 1? '先生' : '女士'}} 17 | {{item.phone}} 18 |
      19 |
      20 | {{item.tag}} 21 |

      {{item.address_detail}}

      22 |
      23 |
      24 |
    • 25 |
    26 |
    27 |
    以下地址超出配送范围
    28 |
      29 |
    • 30 | 31 | 32 | 33 |
      34 |
      35 | {{item.name}} 36 | {{item.sex == 1? '先生' : '女士'}} 37 | {{item.phone}} 38 |
      39 |
      40 | {{item.tag}} 41 |

      {{item.address_detail}}

      42 |
      43 |
      44 |
    • 45 |
    46 |
    47 |
    48 |
    49 | 53 |
    54 |
    -------------------------------------------------------------------------------- /src/app/order/order.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 订单 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 |

    您最近没有订单

    12 |
    13 |
      14 |
    • 15 | 16 |
      17 |
      18 |
      19 |
      20 |

      21 | {{item.restaurant_name}} 22 | 23 | 24 | 25 |

      26 |

      {{item.formatted_created_at}}

      27 |
      28 |

      29 | {{item.status_bar.title}} 30 |

      31 |
      32 |
      33 |

      {{item.basket.group[0][0].name}}{{item.basket.group[0].length > 1 ? ' 等' + item.basket.group[0].length + '件商品' 34 | : ''}}

      35 |

      ¥{{item.total_amount.toFixed(2)}}

      36 |
      37 |
      38 |
      39 |
      40 | {{item.time_pass|timeLast}} 41 |
      42 | 再来一单 43 |
      44 |
      45 |
    • 46 |
    47 |
    48 | 49 |

    没有更多了

    50 | 51 | 52 | 53 |
    -------------------------------------------------------------------------------- /src/app/address/add-address/add-address.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../../style/mixin.scss"; 2 | .address_page{ 3 | .page_text_container{ 4 | background-color: #fff; 5 | padding: 0 1.16rem; 6 | } 7 | .section_list{ 8 | display: flex; 9 | border-bottom: 0.041rem solid #f5f5f5; 10 | .section_left{ 11 | @include sc(1.16rem, #333); 12 | flex: 2; 13 | line-height: 4.1rem; 14 | } 15 | .section_right{ 16 | flex: 5; 17 | .input_style{ 18 | width: 100%; 19 | height: 4.1rem; 20 | @include sc(1.16rem, #999); 21 | } 22 | .phone_bk{ 23 | border-top: 0.041rem solid #f5f5f5; 24 | } 25 | .phone_add{ 26 | @include fj; 27 | align-items: center; 28 | .phone_add_bk { 29 | @include wh(1.5rem, 1.5rem); 30 | } 31 | } 32 | .choose_sex, .choose_tag { 33 | display: flex; 34 | height: 4.1rem; 35 | border-top: 0.041rem solid #f5f5f5; 36 | align-items: center; 37 | .choose_option{ 38 | @include sc(1rem, #333); 39 | margin-right: 1.33rem; 40 | width: 4rem; 41 | height: 2rem; 42 | line-height: 1.9rem; 43 | text-align: center; 44 | display: inline-block; 45 | border-radius: .1rem; 46 | border: 1px solid #d9d9d9; 47 | } 48 | .choosed{ 49 | color: $blue; 50 | border-color: $blue; 51 | } 52 | } 53 | 54 | .choose_address{ 55 | @include sc(1.16rem, #999); 56 | line-height: 4.1rem; 57 | border-bottom: 0.041rem solid #f5f5f5; 58 | display: flex; 59 | justify-content: space-between; 60 | align-items: center; 61 | .address_name { 62 | color: #999; 63 | } 64 | } 65 | .address_search{ 66 | @include wh(1rem, 1rem); 67 | fill: #999; 68 | } 69 | } 70 | } 71 | .determine{ 72 | background-color: #4cd964; 73 | @include sc(1.16rem, #fff); 74 | text-align: center; 75 | margin: 0 1.16rem; 76 | line-height: 3rem; 77 | border-radius: 0.33rem; 78 | margin-top: 1rem; 79 | } 80 | } -------------------------------------------------------------------------------- /src/app/shared/components/shop/evaluate/evaluate.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 |
    6 |

    {{rating}}

    7 |

    综合评价

    8 |

    高于周边商家{{(ratingScoresData?.compare_rating*100).toFixed(1)}}%

    9 |
    10 |
    11 |

    12 | 服务态度 13 | 14 | {{ratingScoresData?.service_score.toFixed(1)}} 15 |

    16 |

    17 | 菜品评价 18 | 19 | {{ratingScoresData?.food_score?.toFixed(1)}} 20 |

    21 |

    22 | 送达时间 23 | {{ratingScoresData?.deliver_time}}分钟 24 |

    25 |
    26 |
    27 |
      28 |
    • 29 | 30 |
      31 |
      32 |
      33 |

      {{item.username}}

      34 |

      35 | 36 | {{item.time_spent_desc}} 37 |

      38 |
      39 | 40 |
      41 |
        42 |
      • 43 | 44 |
      • 45 |
      46 |
        47 |
      • 48 | {{item.food_name}} 49 |
      • 50 |
      51 |
      52 |
    • 53 |
    54 |
    55 |
    56 |
    57 |

    没有更多了

    58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/app/address/add-address/add-address.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
    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 | {{searchAddress()? searchAddress().name : '小区/写字楼/学校等'}} 32 | 33 | 34 | 35 |
    36 | 37 |
    38 |
    39 |
    40 | 标签 41 |
    42 |
    43 | 44 | 学校 45 | 公司 46 |
    47 |
    48 |
    49 |
    50 |
    确定
    51 |
    52 |
    -------------------------------------------------------------------------------- /src/app/city/city.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { AppService, DataService, LocalStorageService } from '../service'; 4 | 5 | @Component({ 6 | selector: 'page-city', 7 | templateUrl: 'city.page.html', 8 | styleUrls: ['city.page.scss'] 9 | }) 10 | export class CityPage implements OnInit { 11 | search: string; 12 | guessCity: string; 13 | guessCityId: string; 14 | placeList: any[]; 15 | placeNone: boolean; 16 | placeHistory: any[]; 17 | historyTitle: boolean; 18 | constructor( 19 | public router: Router, 20 | public route: ActivatedRoute, 21 | public appService: AppService, 22 | public dataService: DataService, 23 | public storageService: LocalStorageService) { 24 | this.guessCityId = this.route.snapshot.paramMap.get('id'); 25 | this.guessCity = ''; 26 | this.search = ''; 27 | this.placeList = []; 28 | this.placeHistory = []; 29 | this.historyTitle = true; 30 | this.getCityById(this.guessCityId); 31 | } 32 | 33 | ngOnInit() { 34 | if (this.storageService.getStore('placeHistory')) { 35 | this.placeList = JSON.parse(this.storageService.getStore('placeHistory')); 36 | } else { 37 | this.placeList = []; 38 | } 39 | } 40 | 41 | getCityById(id: string) { 42 | this.dataService.getCityById(id).subscribe(res => { 43 | this.guessCity = res.name; 44 | }); 45 | } 46 | 47 | setSearchStorage(place: any) { 48 | const history = this.storageService.getStore('placeHistory'); 49 | const choosePlace = place; 50 | if (history) { 51 | let checkrepeat = false; 52 | this.placeHistory = JSON.parse(history); 53 | this.placeHistory.forEach(item => { 54 | if (item.geohash === place.geohash) { 55 | checkrepeat = true; 56 | } 57 | }); 58 | if (!checkrepeat) { 59 | this.placeHistory.push(choosePlace); 60 | } 61 | } else { 62 | this.placeHistory.push(choosePlace); 63 | } 64 | this.storageService.setStore('placeHistory', this.placeHistory); 65 | } 66 | 67 | searchPlace() { 68 | if (!this.search) { 69 | return; 70 | } 71 | this.historyTitle = false; 72 | this.dataService.searchPlace(this.guessCityId, this.search).subscribe(res => { 73 | this.placeList = res; 74 | this.placeNone = res.length ? false : true; 75 | }); 76 | } 77 | 78 | clearAll() { 79 | this.storageService.removeStore('placeHistory'); 80 | this.placeList = []; 81 | } 82 | 83 | toMiste(place: any) { 84 | this.setSearchStorage(place); 85 | this.appService.geohash = place.geohash; 86 | this.router.navigateByUrl('/tabs/msite?geohash=' + place.geohash); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/app/order/order.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnDestroy } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { AlertController } from '@ionic/angular'; 4 | import { AppService, DataService, LocalStorageService } from '../service'; 5 | import { ImgBaseUrl } from '../config/env'; 6 | import { UserInfo } from '../class'; 7 | 8 | @Component({ 9 | selector: 'page-order', 10 | templateUrl: 'order.page.html', 11 | styleUrls: ['order.page.scss'] 12 | }) 13 | export class OrderPage extends UserInfo implements OnInit, OnDestroy { 14 | orderList: any; 15 | showLoading: boolean = true; 16 | offset: number = 0; 17 | imgBaseUrl: string = ImgBaseUrl; 18 | touchEnd: boolean = false; 19 | preventRepeatReuqest: boolean = false; // 到达底部加载数据,防止重复加载 20 | params: {geohash: string}; 21 | constructor( 22 | public route: ActivatedRoute, 23 | public router: Router, 24 | public appService: AppService, 25 | public dataService: DataService, 26 | public localStorageService: LocalStorageService, 27 | public alertCtrl: AlertController) { 28 | super(appService, localStorageService); 29 | } 30 | 31 | ngOnInit() { 32 | this.params = { geohash: this.appService.geohash }; 33 | this.orderList = []; 34 | if (this.userId) { 35 | this.dataService.getOrderList(this.userId, this.offset).subscribe(res => { 36 | this.orderList = [...res]; 37 | this.showLoading = false; 38 | }); 39 | } else { 40 | this.showLoading = false; 41 | } 42 | } 43 | 44 | loaderMore(event: any) { 45 | this.offset += 10; 46 | this.preventRepeatReuqest = true; 47 | this.showLoading = true; 48 | const userId = this.localStorageService.getStore('userId'); 49 | this.dataService.getOrderList(userId, this.offset).subscribe(res => { 50 | if (res.length < 10) { 51 | this.touchEnd = true; 52 | event.target.disabled = true; 53 | } 54 | this.orderList = [...this.orderList, ...res]; 55 | this.showLoading = false; 56 | this.preventRepeatReuqest = false; 57 | }); 58 | event.target.complete(); 59 | } 60 | // 显示详情页 61 | showDetail(item: any) { 62 | this.appService.orderDetail = item; 63 | this.preventRepeatReuqest = false; 64 | this.router.navigateByUrl('/order/detail'); 65 | } 66 | 67 | async presentConfirm(message: string) { 68 | const alert = await this.alertCtrl.create({ 69 | header: '确认支付', 70 | message: message, 71 | cssClass: 'confirm', 72 | buttons: [ 73 | { 74 | text: '确认', 75 | handler: () => { 76 | this.router.navigateByUrl('/tabs/order'); 77 | } 78 | } 79 | ] 80 | }); 81 | alert.present(); 82 | } 83 | 84 | toPay() { 85 | this.presentConfirm('付款功能未开放'); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ionic6_angular10_elm 2 | 基于ionic6 + ng10构建一个具有 30+ 页面的大型单页面应用(master必须使用ionic v6,已升级到v6正式版) 3 | 4 | [阿里移动端组件库ng-zorro-antd-mobile开源地址](https://github.com/NG-ZORRO/ng-zorro-antd-mobile),将在zorro分支逐步使用zorro-antd-mobile组件替换重构,感兴趣的可以直接使用zorro分支(重构中,未完成) 5 | 6 | 基于ionic5 + ng8 构建一个具有 30+ 页面的大型单页面应用(请使用ionic5-ng8分支) 7 | 8 | 基于ionic3 + ng5 构建一个具有 30+ 页面的大型单页面应用(请使用v3分支,必须使用ionic v3才能启动) 9 | 借鉴了[@bailicangdu](https://github.com/bailicangdu/vue2-elm) vue-elm项目,已征得其本人同意,[后台传送地址](https://github.com/bailicangdu/node-elm) 10 | 11 | 12 | 13 | ## 项目运行 14 | 15 | #### 注意:由于涉及大量的 ES6/7 等新属性,node 需要 6.0 以上版本 16 | 17 | ``` 18 | npm install -g cordova ionic // 需要全局安装cordova ionic 19 | 20 | git clone https://github.com/nuonuoge/ionic4_angular6_elm.git   21 | 22 | cd ionic4_angular6_elm 23 | 24 | npm install 25 | 26 | npm start 27 | 28 | ``` 29 | 30 | ## 另外 31 | 此项目有配套的后台系统,如果想体验前后台同时开发,可以下载对应的后台系统:[后台项目传送地址](https://github.com/bailicangdu/node-elm)。 32 | 33 | 如果只做前端开发,请忽略这句话。 34 | 35 | 36 | # 说明 37 | 38 | > 暂时没有体验地址,待所有功能完成后再发布,可以去[vue-elm发布地址体验](http://cangdu.org/elm/)(请用chrome手机模式预览) 39 | 40 | > 如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢! ^_^ 41 | 42 | > 或者您可以 "follow" 一下,我会不断开源更多的有趣的项目 43 | 44 | > 如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR 👍 45 | 46 | > 推荐一个 react + redux 开源项目,对react感兴趣的朋友赶紧去看看。[地址在这里](https://github.com/bailicangdu/react-pxq) 47 | 48 | > 另外一个 vue2 + vuex 的elm项目。[地址在这里](https://github.com/bailicangdu/vue2-elm) 49 | 50 | # 部分展示 51 | ### 登录页 52 | 53 | 54 | ### 搜索页 55 | 56 | 57 | ### tabs 58 | 59 | 60 | ### 商铺列表页 61 |        62 | 63 | ### 商铺页 64 |        65 | 66 | # 目标功能 67 | - [x] 定位功能 -- 完成 68 | - [x] 选择城市 -- 完成 69 | - [x] 搜索地址 -- 完成 70 | - [x] 展示所选地址附近商家列表 -- 完成 71 | - [x] 搜索美食,餐馆 -- 完成 72 | - [x] 根据距离、销量、评分、特色菜、配送方式等进行排序和筛选 -- 完成 73 | - [x] 餐馆食品列表页 -- 完成 74 | - [x] 购物车功能 -- 完成 75 | - [x] 店铺评价页面 -- 完成 76 | - [x] 单个食品详情页面 -- 完成 77 | - [x] 商家详情页 -- 完成 78 | - [x] 登录、注册 -- 完成 79 | - [x] 个人中心 -- 完成 80 | - [x] 下单功能 -- 完成 81 | - [x] 订单列表 -- 完成 82 | - [x] 订单详情 -- 完成 83 | 84 | # License 85 | 86 | GPL 87 | -------------------------------------------------------------------------------- /src/app/shared/components/buy-cart/buy-cart.ts: -------------------------------------------------------------------------------- 1 | import { Component, EventEmitter, Input, Output } from '@angular/core'; 2 | import { ToastController } from '@ionic/angular'; 3 | import { LocalStorageService, CartService } from '../../../service'; 4 | 5 | @Component({ 6 | selector: 'buy-cart', 7 | templateUrl: 'buy-cart.html', 8 | styleUrls: ['buy-cart.scss'] 9 | }) 10 | export class BuyCartComponent { 11 | @Input() foods: any; 12 | @Input() shopId: string; 13 | @Output() onCartChange: EventEmitter = new EventEmitter(); 14 | @Output() onShowChooseList: EventEmitter = new EventEmitter(); 15 | @Output() onShowMoveDot: EventEmitter = new EventEmitter(); 16 | showMoveDot: any = []; 17 | constructor(public storageService: LocalStorageService, public cartService: CartService, public toastCtrl: ToastController) { 18 | 19 | } 20 | shopCart() { 21 | return Object.assign({}, this.cartService.cartList[this.shopId]); 22 | } 23 | // shopCart变化的时候重新计算当前商品的数量 24 | foodNum() { 25 | const category_id = this.foods.category_id; 26 | const item_id = this.foods.item_id; 27 | if (this.shopCart() && this.shopCart()[category_id] && this.shopCart()[category_id][item_id]) { 28 | let num = 0; 29 | const values = []; 30 | Object.keys(this.shopCart()[category_id][item_id]).forEach(item => { 31 | values.push(this.shopCart()[category_id][item_id][item]); 32 | }); 33 | values.forEach((item, index) => { 34 | num += item.num; 35 | }); 36 | return num; 37 | } else { 38 | return 0; 39 | } 40 | } 41 | // 移出购物车 42 | removeOutCart(category_id, item_id, food_id, name, price, specs, packing_fee, sku_id, stock) { 43 | if (this.foodNum() > 0) { 44 | this.cartService.reduceCart({ shopid: this.shopId, category_id, item_id, food_id, name, price, specs, packing_fee, sku_id, stock }); 45 | this.onCartChange.emit(null); 46 | } 47 | } 48 | // 加入购物车,计算按钮位置。 49 | addToCart(category_id, item_id, food_id, name, price, specs, packing_fee, sku_id, stock, event) { 50 | this.cartService.addCart({ shopid: this.shopId, category_id, item_id, food_id, name, price, specs, packing_fee, sku_id, stock }); 51 | this.onCartChange.emit(null); 52 | const elLeft = event.target.getBoundingClientRect().left; 53 | const elBottom = event.target.getBoundingClientRect().bottom; 54 | this.showMoveDot.push(true); 55 | this.onShowMoveDot.emit({ 'showMoveDot': this.showMoveDot, 'elLeft': elLeft, 'elBottom': elBottom }); 56 | 57 | } 58 | // 显示规格列表 59 | showChooseList(foods) { 60 | this.onShowChooseList.emit(foods); 61 | } 62 | // 点击多规格商品的减按钮,弹出提示 63 | async showReduceTip() { 64 | const toast = await this.toastCtrl.create({ 65 | message: '多规格商品只能去购物车删除哦', 66 | duration: 2000, 67 | position: 'middle', 68 | cssClass: 'specs_reduce_tip' 69 | }); 70 | toast.present(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/app/service/cart.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { LocalStorageService } from './localstorage.service'; 3 | 4 | @Injectable({ 5 | providedIn: 'root' 6 | }) 7 | 8 | export class CartService { 9 | public cartList: any; 10 | constructor(public storageService: LocalStorageService) { 11 | this.cartList = {}; 12 | } 13 | 14 | // 加入购物车 15 | addCart(cartObject: { 16 | shopid?: string, 17 | category_id?: string, 18 | item_id?: string, 19 | food_id?: string, 20 | name?: string, 21 | price?: any, 22 | specs?: any, 23 | packing_fee?: any, 24 | sku_id?: string, 25 | stock?: any 26 | }) { 27 | const cart = this.cartList; 28 | const shop = cart[cartObject.shopid] = (cart[cartObject.shopid] || {}); 29 | const category = shop[cartObject.category_id] = (shop[cartObject.category_id] || {}); 30 | const item = category[cartObject.item_id] = (category[cartObject.item_id] || {}); 31 | if (item[cartObject.food_id]) { 32 | item[cartObject.food_id]['num']++; 33 | } else { 34 | item[cartObject.food_id] = { 35 | 'num': 1, 36 | 'id': cartObject.food_id, 37 | 'name': cartObject.name, 38 | 'price': cartObject.price, 39 | 'specs': cartObject.specs, 40 | 'packing_fee': cartObject.packing_fee, 41 | 'sku_id': cartObject.sku_id, 42 | 'stock': cartObject.stock 43 | }; 44 | } 45 | this.cartList = { ...cart }; 46 | // 存入localStorage 47 | this.storageService.setStore('buyCart', this.cartList); 48 | } 49 | // 移出购物车 50 | reduceCart(cartObject: { 51 | shopid?: string, 52 | category_id?: string, 53 | item_id?: string, 54 | food_id?: string, 55 | name?: string, 56 | price?: any, 57 | specs?: any, 58 | packing_fee?: any, 59 | sku_id?: string, 60 | stock?: any 61 | }) { 62 | const cart = this.cartList; 63 | const shop = (cart[cartObject.shopid] || {}); 64 | const category = (shop[cartObject.category_id] || {}); 65 | const item = (category[cartObject.item_id] || {}); 66 | if (item && item[cartObject.food_id]) { 67 | if (item[cartObject.food_id]['num'] > 0) { 68 | item[cartObject.food_id]['num']--; 69 | this.cartList = { ...cart }; 70 | // 存入localStorage 71 | this.storageService.setStore('buyCart', this.cartList); 72 | } else { 73 | // 商品数量为0,则清空当前商品的信息 74 | item[cartObject.food_id] = null; 75 | } 76 | } 77 | } 78 | // 网页初始化时从本地缓存获取购物车数据 79 | initBuyCart() { 80 | const initCart = this.storageService.getStore('buyCart'); 81 | if (initCart) { 82 | this.cartList = JSON.parse(initCart); 83 | } 84 | } 85 | // 清空当前商品的购物车信息 86 | clearCart(shopId) { 87 | this.cartList[shopId] = null; 88 | this.cartList = { ...this.cartList }; 89 | this.storageService.setStore('buyCart', this.cartList); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/app/search/search.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { DataService, LocalStorageService } from '../service'; 4 | 5 | @Component({ 6 | selector: 'page-search', 7 | templateUrl: 'search.page.html', 8 | styleUrls: ['./search.page.scss'] 9 | }) 10 | export class SearchPage implements OnInit { 11 | searchValue: string; 12 | geohash: string; 13 | restaurantList: any[]; 14 | emptyResult: boolean; 15 | searchHistory: any[]; 16 | showHistory: boolean; 17 | 18 | constructor(public route: ActivatedRoute, 19 | public router: Router, 20 | public dataService: DataService, 21 | public storageService: LocalStorageService) { 22 | this.geohash = this.route.snapshot.queryParamMap.get('geohash'); 23 | this.searchValue = ''; 24 | this.restaurantList = []; 25 | this.searchHistory = []; 26 | this.showHistory = true; 27 | } 28 | 29 | ngOnInit() { 30 | if (this.storageService.getStore('searchHistory')) { 31 | this.searchHistory = JSON.parse(this.storageService.getStore('searchHistory')); 32 | } else { 33 | this.searchHistory = []; 34 | } 35 | } 36 | 37 | setSearchStorage() { 38 | const history = this.storageService.getStore('searchHistory'); 39 | if (history) { 40 | let checkrepeat = false; 41 | this.searchHistory = JSON.parse(history); 42 | this.searchHistory.forEach(item => { 43 | if (item === this.searchValue) { 44 | checkrepeat = true; 45 | } 46 | }); 47 | if (!checkrepeat) { 48 | this.searchHistory.push(this.searchValue); 49 | } 50 | } else { 51 | this.searchHistory.push(this.searchValue); 52 | } 53 | this.storageService.setStore('searchHistory', this.searchHistory); 54 | } 55 | 56 | searchRestaurants(value?: string) { 57 | if (value) { 58 | this.searchValue = value; 59 | } else if (!this.searchValue) { 60 | return; 61 | } 62 | this.showHistory = false; 63 | this.dataService.searchRestaurant(this.geohash, this.searchValue).subscribe((res: any) => { 64 | this.restaurantList = res; 65 | this.emptyResult = res.length ? false : true; 66 | }); 67 | this.setSearchStorage(); 68 | } 69 | 70 | checkInput() { 71 | if (this.searchValue === '') { 72 | this.showHistory = true; // 显示历史记录 73 | this.restaurantList = []; // 清空搜索结果 74 | this.emptyResult = false; // 隐藏搜索为空提示 75 | } 76 | } 77 | 78 | deleteHistory(index: number) { 79 | this.searchHistory.splice(index, 1); 80 | this.storageService.setStore('searchHistory', this.searchHistory); 81 | } 82 | 83 | clearAll() { 84 | this.storageService.removeStore('searchHistory'); 85 | this.searchHistory = []; 86 | this.restaurantList = []; 87 | } 88 | 89 | toShop(place: any) { 90 | this.router.navigate(['msite'], { queryParams: { geohash: place.geohash } }); 91 | } 92 | 93 | back() { 94 | window.history.back(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/app/order/order.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../style/mixin.scss"; 2 | @import "../../style/common.scss"; 3 | 4 | .order_empty { 5 | height: 100%; 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | justify-content: center; 10 | .order_empty_icon { 11 | background-repeat: no-repeat; 12 | height: 6rem; 13 | width: 6rem; 14 | } 15 | .order_empty_text { 16 | font-size: 1rem; 17 | color: #999; 18 | margin-top: .5rem; 19 | } 20 | } 21 | .order_list_ul{ 22 | .order_list_li{ 23 | background-color: #fff; 24 | display: flex; 25 | margin-bottom: 0.83rem; 26 | padding: 1rem 1rem 0; 27 | .restaurant_image{ 28 | @include wh(3.3rem, 3.3rem); 29 | margin-right: 0.67rem; 30 | } 31 | .order_item_right{ 32 | flex: 5; 33 | .order_item_right_header{ 34 | border-bottom: 0.041rem solid #f5f5f5; 35 | padding-bottom: .5rem; 36 | padding-right: 1rem; 37 | @include fj; 38 | .order_header{ 39 | h4{ 40 | display: flex; 41 | align-items: center; 42 | justify-content: flex-start; 43 | @include sc(1.25rem, #333); 44 | line-height: 1.67rem; 45 | width: 15rem; 46 | .arrow_right{ 47 | @include wh(.67rem, .67rem); 48 | fill: #ccc; 49 | margin-right: .33rem; 50 | } 51 | } 52 | .order_time{ 53 | @include sc(.92rem, #999); 54 | line-height: 1.33rem; 55 | } 56 | } 57 | .order_status{ 58 | @include sc(1rem, #333); 59 | } 60 | } 61 | .order_basket{ 62 | @include fj; 63 | padding-right: 1rem; 64 | line-height: 3.3rem; 65 | border-bottom: 0.041rem solid #f5f5f5; 66 | .order_name{ 67 | @include sc(1rem, #666); 68 | width: 15rem; 69 | } 70 | .order_amount{ 71 | @include sc(1rem, #f60); 72 | font-weight: bold; 73 | } 74 | } 75 | .order_again{ 76 | text-align: right; 77 | line-height: 2.6rem; 78 | margin-right: 1rem; 79 | .buy_again{ 80 | @include sc(.92rem, #3190e8); 81 | border: 0.055rem solid #3190e8; 82 | padding: .26rem .33rem; 83 | border-radius: .25rem; 84 | } 85 | .page{ 86 | display: inline-block; 87 | .wait_pay { 88 | font-size: .92rem; 89 | color: orange; 90 | border: 1px solid orange; 91 | border-radius: .15rem; 92 | padding: .1rem .2rem; 93 | } 94 | .rem_time{ 95 | @include sc(.92rem, orange); 96 | padding: .16rem .33rem; 97 | border-radius: .25rem; 98 | } 99 | } 100 | } 101 | } 102 | } 103 | } 104 | .empty_data{ 105 | @include sc(0.82rem, #666); 106 | text-align: center; 107 | line-height: 3.34rem; 108 | } -------------------------------------------------------------------------------- /src/assets/icon/find.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags.ts'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | import './zone-flags'; 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | 61 | import 'zone.js/dist/zone'; // Included with Angular CLI. 62 | 63 | 64 | /*************************************************************************************************** 65 | * APPLICATION IMPORTS 66 | */ 67 | -------------------------------------------------------------------------------- /src/app/profile/profile.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 我的 7 | 8 | 9 |
    10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 |
    29 |
    30 | 31 | 32 |
    33 |
      34 | 38 | 42 | 46 |
    47 |
    48 |
    49 | 50 |
    51 | 56 |
    57 | 我的订单 58 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 66 |
    67 | 72 |
    73 | 收货地址 74 | 75 | 76 | 77 | 78 | 79 |
    80 |
    81 |
    82 |
    83 | 退出登录 84 |
    85 |
    -------------------------------------------------------------------------------- /src/app/order/order-detail/order-detail.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
    6 |
    7 | 8 |

    {{orderDetail.status_bar.title}}

    9 |

    {{orderDetail.timeline_node.description}}

    10 |
    再来一单
    11 |
    12 |
    13 |
    14 |
    15 | 16 | {{orderDetail.restaurant_name}} 17 |
    18 | 19 | 20 | 21 |
    22 |
      23 |
    • 24 |

      {{item.name}}

      25 |
      26 | X{{item.quantity}} 27 | ¥{{item.price}} 28 |
      29 |
    • 30 |
    31 |
    32 | 配送费 33 | {{orderDetail.basket.deliver_fee&&orderDetail.basket.deliver_fee.price || 0}} 34 |
    35 |
    实付{{orderDetail.total_amount.toFixed(2)}}
    36 |
    37 |
    38 |
    配送信息
    39 |
    40 |

    送达时间:

    41 |
    42 |

    {{orderData.deliver_time}}

    43 |
    44 |
    45 |
    46 |

    送货地址:

    47 |
    48 |

    {{orderData.consignee}}

    49 |

    {{orderData.phone}}

    50 |

    {{orderData.address}}

    51 |
    52 |
    53 |
    54 |

    配送方式:

    55 |
    56 |

    蜂鸟专送

    57 |
    58 |
    59 |
    60 |
    61 |
    订单信息
    62 |
    63 |

    订单号:

    64 |
    65 |

    {{orderDetail.id}}

    66 |
    67 |
    68 |
    69 |

    支付方式:

    70 |
    71 |

    在线支付

    72 |
    73 |
    74 |
    75 |

    下单时间:

    76 |
    77 |

    {{orderDetail.formatted_created_at}}

    78 |
    79 |
    80 |
    81 |
    82 | 83 |
    -------------------------------------------------------------------------------- /src/app/shop/detail/shop-detail.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
    6 |
    7 |
    8 | 9 |
    10 |
    11 |

    {{shopDetailData.name}}

    12 |

    13 | 14 | {{shopDetailData.rating.toFixed(1)}} 15 | 月售{{shopDetailData.recent_order_num}}单 16 |

    17 |

    18 | {{shopDetailData.float_minimum_order_amount}}元起送/{{ratingScoresData.deliver_time}}分钟 19 | 20 | {{shopDetailData?.delivery_mode?.text}} 21 |

    22 |
    23 |
    24 |
    25 |

    配送费: 配送费¥{{shopDetailData.float_delivery_fee}}

    26 |

    公告: {{shopDetailData.promotion_info}}

    27 |
    28 |
    29 | 30 |
    31 |
    32 | {{shopDetailData.rating.toFixed(1)}}分 高于周边商家{{(ratingScoresData?.compare_rating*100).toFixed(1)}}% 33 |
    34 |
    35 | 36 |
    37 |

    {{rating.username}}

    38 |

    39 | 40 |

    41 |
    42 | 43 |
    44 |
    查看全部评价
    45 |
    46 |
    47 |
    活动与属性
    48 |
  • 49 | {{item.icon_name}} 50 | {{item.description}} 51 |
  • 52 |
  • 53 | {{item.icon_name}} 54 | {{item.description}} 55 |
  • 56 |
    57 |
    58 |
    商家信息
    59 |

    叫外卖,上饿了么

    60 |

    地址:{{shopDetailData.address}}

    61 |

    营业时间:{{time}}

    62 |
    63 |
    -------------------------------------------------------------------------------- /src/app/order/order-detail/order-detail.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../../style/mixin.scss"; 2 | @import "../../../style/common.scss"; 3 | 4 | .order_title{ 5 | display: flex; 6 | flex-direction: column; 7 | align-items: center; 8 | padding: 1.16rem; 9 | background-color: #fff; 10 | margin-bottom: 0.83rem; 11 | img{ 12 | border: 0.08rem solid $blue; 13 | border-radius: 50%; 14 | @include wh(5rem, 5rem); 15 | } 16 | p:nth-of-type(1){ 17 | @include sc(1.5rem, #333); 18 | font-weight: bold; 19 | margin-top: .67rem; 20 | } 21 | p:nth-of-type(2){ 22 | @include sc(.92rem, #999); 23 | width: 16.7rem; 24 | margin-top: .5rem; 25 | text-align: center; 26 | } 27 | .order_again{ 28 | @include sc(1rem, $blue); 29 | margin-top: .83rem; 30 | border: 0.041rem solid $blue; 31 | padding: .25rem .67rem; 32 | border-radius: .16rem; 33 | } 34 | } 35 | .food_list{ 36 | background-color: #fff; 37 | .food_list_header{ 38 | @include fj; 39 | align-items: center; 40 | padding: .33rem .83rem; 41 | border-bottom: 1px solid #f5f5f5; 42 | .shop_name{ 43 | img{ 44 | @include wh(2rem, 2rem); 45 | vertical-align: middle; 46 | margin-right: .33rem; 47 | } 48 | span{ 49 | @include sc(1.25rem, #333); 50 | font-weight: bold; 51 | } 52 | } 53 | svg{ 54 | @include wh(1rem, 1rem); 55 | fill: #666; 56 | } 57 | } 58 | .food_list_ul{ 59 | li{ 60 | @include fj; 61 | align-items: center; 62 | padding: 0 .83rem; 63 | line-height: 3.3rem; 64 | .food_name{ 65 | @include sc(1rem, #666); 66 | flex: 4; 67 | } 68 | .quantity_price{ 69 | flex: 1; 70 | @include fj; 71 | align-items: center; 72 | span:nth-of-type(1){ 73 | @include sc(1rem, #ccc); 74 | } 75 | span:nth-of-type(2){ 76 | @include sc(1rem, #666); 77 | } 78 | } 79 | } 80 | } 81 | .deliver_fee{ 82 | @include fj; 83 | align-items: center; 84 | padding: 0 .83rem; 85 | line-height: 3.3rem; 86 | border-top: 1px solid #f5f5f5; 87 | span{ 88 | @include sc(1rem, #666); 89 | } 90 | } 91 | .pay_ment{ 92 | @include sc(1rem, #fb6b23); 93 | border-top: 1px solid #f5f5f5; 94 | font-weight: bold; 95 | line-height: 3.3rem; 96 | text-align: right; 97 | padding-right: .83rem; 98 | } 99 | } 100 | .order_detail_style{ 101 | background-color: #fff; 102 | margin-top: 0.83rem; 103 | header{ 104 | @include sc(1.25rem, #333); 105 | padding: .83rem; 106 | border-bottom: 1px solid #f5f5f5; 107 | } 108 | .item_style{ 109 | display: flex; 110 | padding: .83rem; 111 | p{ 112 | @include sc(1.1rem, #666); 113 | line-height: 1.67rem; 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /src/app/shared/components/shop/msite/shop-msite.scss: -------------------------------------------------------------------------------- 1 | @import "../../../../../style/mixin.scss"; 2 | .shoplist_container{ 3 | background-color: #fff; 4 | margin-bottom: 3.34rem; 5 | } 6 | .shop_li{ 7 | display: flex; 8 | border-bottom: 0.06rem solid #f1f1f1; 9 | padding: 1.16rem 0.668rem; 10 | } 11 | .shop_img{ 12 | @include wh(4.5rem, 4.5rem); 13 | display: block; 14 | margin-right: 0.668rem; 15 | } 16 | .list_back_li{ 17 | height: 8.1rem; 18 | .list_back_svg{ 19 | @include wh(100%, 100%) 20 | } 21 | } 22 | .shop_right{ 23 | flex: auto; 24 | .shop_detail_header{ 25 | @include fj; 26 | align-items: center; 27 | .shop_title{ 28 | width: 14.2rem; 29 | color: #333; 30 | padding-top: .016rem; 31 | @include font(1.08rem, 1.08rem, 'PingFangSC-Regular'); 32 | font-weight: 700; 33 | } 34 | .premium::before{ 35 | content: '品牌'; 36 | display: inline-block; 37 | font-size: 0.83rem; 38 | line-height: 1rem; 39 | color: #333; 40 | background-color: #ffd930; 41 | padding: 0 0.16rem; 42 | border-radius: 0.16rem; 43 | margin-right: 0.33rem; 44 | } 45 | .shop_detail_ul{ 46 | display: flex; 47 | transform: scale(.8); 48 | margin-right: -0.5rem; 49 | .supports{ 50 | @include sc(0.835rem, #999); 51 | border: 0.06rem solid #f1f1f1; 52 | padding: 0 0.0668rem; 53 | border-radius: 0.13rem; 54 | margin-left: 0.083rem; 55 | } 56 | } 57 | } 58 | .rating_order_num{ 59 | @include fj(space-between); 60 | height: 1rem; 61 | margin-top: 0.87rem; 62 | .rating_order_num_left{ 63 | @include fj(flex-start); 64 | .rating_section{ 65 | display: flex; 66 | .rating_num{ 67 | @include sc(0.668rem, #ff6000); 68 | margin: 0 0.334rem; 69 | } 70 | } 71 | .order_section{ 72 | transform: scale(.8); 73 | margin-left: -0.334rem; 74 | @include sc(0.668rem, #666); 75 | } 76 | } 77 | .rating_order_num_right{ 78 | display: flex; 79 | align-items: center; 80 | transform: scale(.7); 81 | min-width: 8.35rem; 82 | justify-content: flex-end; 83 | margin-right: -1.336rem; 84 | .delivery_style{ 85 | font-size: 0.668rem; 86 | padding: 0.0668rem 0.13rem 0; 87 | border-radius: 0.13rem; 88 | margin-left: 0.13rem; 89 | border: 1px; 90 | } 91 | .delivery_left{ 92 | color: #fff; 93 | background-color: $blue; 94 | border: 0.06rem solid $blue; 95 | } 96 | .delivery_right{ 97 | color: $blue; 98 | border: 0.06rem solid $blue; 99 | } 100 | } 101 | } 102 | .fee_distance{ 103 | margin-top: 0.87rem; 104 | @include fj; 105 | @include sc(0.835rem, #333); 106 | .fee{ 107 | transform: scale(.9); 108 | @include sc(0.835rem, #666); 109 | } 110 | .distance_time{ 111 | transform: scale(.9); 112 | span{ 113 | color: #999; 114 | } 115 | .order_time{ 116 | color: $blue; 117 | } 118 | .segmentation{ 119 | color: #ccc; 120 | } 121 | } 122 | } 123 | } 124 | .loader_more{ 125 | @include font(1rem, 3); 126 | text-align: center; 127 | color: #999; 128 | } 129 | .return_top{ 130 | position: fixed; 131 | bottom: 5rem; 132 | right: 1.67rem; 133 | .back_top_svg{ 134 | @include wh(3.34rem, 3.34rem); 135 | } 136 | } 137 | .loading-enter-active, .loading-leave-active { 138 | transition: opacity 1s 139 | } 140 | .loading-enter, .loading-leave-active { 141 | opacity: 0 142 | } -------------------------------------------------------------------------------- /src/app/address/add-address/add-address.page.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { ToastController } from '@ionic/angular'; 4 | import { DataService, LocalStorageService, AppService } from '../../service'; 5 | import { UserInfo } from '../../class'; 6 | 7 | @Component({ 8 | selector: 'page-add-address', 9 | templateUrl: 'add-address.page.html', 10 | styleUrls: ['./add-address.page.scss'] 11 | }) 12 | export class AddAddressPage extends UserInfo { 13 | name: string = null; // 姓名 14 | sex: number = 1; // 性别 15 | phone: string = null; // 电话 16 | phoneBk: boolean = false; // 备用电话 17 | addressDetail: string = null; // 详细地址 18 | tag: string = ''; // 备注 19 | tagType: number = 1; // 备注类型 20 | phone_bk: boolean = false; // 是否选择备注电话 21 | anntherPhoneNumber: string = ''; // 备注电话 22 | showAlert: boolean = false; // 弹出框 23 | fromWhere: string; 24 | constructor( 25 | public route: ActivatedRoute, 26 | public router: Router, 27 | public localStorageService: LocalStorageService, 28 | public appService: AppService, 29 | public dataService: DataService, 30 | public toastCtrl: ToastController) { 31 | super(appService, localStorageService); 32 | this.fromWhere = this.route.snapshot.queryParamMap.get('from'); 33 | } 34 | 35 | searchAddress(): any { 36 | return this.appService.searchAddress; 37 | } 38 | 39 | // 选择性别 40 | chooseSex(sex) { 41 | this.sex = sex; 42 | } 43 | // 选择标签 44 | chooseTag(tag) { 45 | this.tag = tag; 46 | } 47 | 48 | async toastTip(message: string) { 49 | const toast = await this.toastCtrl.create({ 50 | message: message, 51 | duration: 2000, 52 | position: 'bottom' 53 | }); 54 | toast.present(); 55 | } 56 | 57 | // 保存地址信息 58 | addAddress() { 59 | let alertText = ''; 60 | if (!this.userId) { 61 | alertText = '请登录'; 62 | } else if (!this.name) { 63 | this.showAlert = true; 64 | alertText = '请输入姓名'; 65 | } else if (!this.phone) { 66 | this.showAlert = true; 67 | alertText = '请输入电话号码'; 68 | } else if (!this.searchAddress()) { 69 | this.showAlert = true; 70 | alertText = '请选择地址'; 71 | } else if (!this.addressDetail) { 72 | this.showAlert = true; 73 | alertText = '请输入详细地址'; 74 | } 75 | if (alertText) { 76 | this.toastTip(alertText); 77 | return; 78 | } 79 | if (this.tag === '家') { 80 | this.tagType = 2; 81 | } else if (this.tag === '学校') { 82 | this.tagType = 3; 83 | } else if (this.tag === '公司') { 84 | this.tagType = 4; 85 | } 86 | this.dataService.postAddAddress(this.userId, this.searchAddress().name, this.addressDetail, 87 | this.appService.geohash, this.name, this.phone, this.anntherPhoneNumber, 0, 88 | this.sex, this.tag, this.tagType) 89 | .subscribe(res => { 90 | // 保存成功返沪上一页,否则弹出提示框 91 | if (res.message) { 92 | this.toastTip(res.message); 93 | } else { 94 | this.appService.searchAddress = ''; 95 | this.appService.notify.emit('refresh'); 96 | if (this.fromWhere === 'searchAddress') { 97 | this.router.navigate(['/confirmOrder', 'chooseAddress']); 98 | } else { 99 | this.router.navigate(['/address']); 100 | } 101 | } 102 | }); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rules": { 4 | "align": { 5 | "options": [ 6 | "statements" 7 | ] 8 | }, 9 | "array-type": false, 10 | "arrow-return-shorthand": true, 11 | "curly": true, 12 | "deprecation": { 13 | "severity": "warning" 14 | }, 15 | "component-class-suffix": [true, "Page", "Component"], 16 | "contextual-lifecycle": true, 17 | "directive-class-suffix": true, 18 | "directive-selector": [ 19 | true, 20 | "attribute", 21 | "app", 22 | "camelCase" 23 | ], 24 | "component-selector": [ 25 | true, 26 | "element", 27 | "kebab-case" 28 | ], 29 | "eofline": true, 30 | "import-blacklist": [ 31 | true, 32 | "rxjs/Rx" 33 | ], 34 | "import-spacing": true, 35 | "indent": { 36 | "options": [ 37 | "spaces" 38 | ] 39 | }, 40 | "max-classes-per-file": false, 41 | "max-line-length": [ 42 | true, 43 | 140 44 | ], 45 | "member-ordering": [ 46 | true, 47 | { 48 | "order": [ 49 | "static-field", 50 | "instance-field", 51 | "static-method", 52 | "instance-method" 53 | ] 54 | } 55 | ], 56 | "no-console": [ 57 | true, 58 | "debug", 59 | "info", 60 | "time", 61 | "timeEnd", 62 | "trace" 63 | ], 64 | "no-empty": false, 65 | "no-inferrable-types": false, 66 | "no-non-null-assertion": true, 67 | "no-redundant-jsdoc": true, 68 | "no-switch-case-fall-through": true, 69 | "no-var-requires": false, 70 | "object-literal-key-quotes": [ 71 | true, 72 | "as-needed" 73 | ], 74 | "quotemark": [ 75 | true, 76 | "single" 77 | ], 78 | "semicolon": { 79 | "options": [ 80 | "always" 81 | ] 82 | }, 83 | "space-before-function-paren": { 84 | "options": { 85 | "anonymous": "never", 86 | "asyncArrow": "always", 87 | "constructor": "never", 88 | "method": "never", 89 | "named": "never" 90 | } 91 | }, 92 | "typedef-whitespace": { 93 | "options": [ 94 | { 95 | "call-signature": "nospace", 96 | "index-signature": "nospace", 97 | "parameter": "nospace", 98 | "property-declaration": "nospace", 99 | "variable-declaration": "nospace" 100 | }, 101 | { 102 | "call-signature": "onespace", 103 | "index-signature": "onespace", 104 | "parameter": "onespace", 105 | "property-declaration": "onespace", 106 | "variable-declaration": "onespace" 107 | } 108 | ] 109 | }, 110 | "variable-name": { 111 | "options": [ 112 | "ban-keywords", 113 | "check-format", 114 | "allow-pascal-case", 115 | "allow-snake-case" 116 | ] 117 | }, 118 | "whitespace": { 119 | "options": [ 120 | "check-branch", 121 | "check-decl", 122 | "check-operator", 123 | "check-separator", 124 | "check-type", 125 | "check-typecast" 126 | ] 127 | }, 128 | "no-conflicting-lifecycle": true, 129 | "no-host-metadata-property": true, 130 | "no-input-rename": true, 131 | "no-inputs-metadata-property": true, 132 | "no-output-native": true, 133 | "no-output-on-prefix": true, 134 | "no-output-rename": true, 135 | "no-outputs-metadata-property": true, 136 | "template-banana-in-box": true, 137 | "template-no-negated-async": true, 138 | "use-lifecycle-interface": true, 139 | "use-pipe-transform-interface": true, 140 | "object-literal-sort-keys": false 141 | }, 142 | "rulesDirectory": [ 143 | "codelyzer" 144 | ] 145 | } -------------------------------------------------------------------------------- /src/app/msite/msite.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { AppService, DataService } from '../service'; 4 | 5 | 6 | @Component({ 7 | selector: 'page-msite', 8 | templateUrl: 'msite.page.html', 9 | styleUrls: ['msite.page.scss'] 10 | }) 11 | export class MsitePage implements OnInit { 12 | geohash: string; 13 | addressTitle: string; 14 | foodTypes: any[]; 15 | slideActive: boolean; 16 | imgBaseUrl = 'https://fuss10.elemecdn.com'; 17 | params: any; 18 | foodParams: any; 19 | hasGetData: boolean; 20 | 21 | shopList: any[]; 22 | latitude: string; 23 | longitude: string; 24 | offset: number; 25 | restaurantCategoryId: string; 26 | touchend: boolean; 27 | showLoading: boolean; 28 | preventRepeatReuqest: boolean = false; // 到达底部加载数据,防止重复加载 29 | 30 | constructor( 31 | public route: ActivatedRoute, 32 | public router: Router, 33 | public appService: AppService, 34 | public dataService: DataService) { 35 | this.geohash = this.route.snapshot.queryParamMap.get('geohash'); 36 | this.offset = 0; 37 | this.shopList = []; 38 | this.touchend = false; 39 | this.showLoading = true; 40 | 41 | } 42 | 43 | ngOnInit() { 44 | if (this.geohash) { 45 | this.latitude = this.geohash.split(',')[0]; 46 | this.longitude = this.geohash.split(',')[1]; 47 | this.params = { geohash: this.geohash }; 48 | this.getPoisGeohash(); 49 | this.getMsiteFoodTypes(); 50 | this.getShopList(); 51 | } else { 52 | this.dataService.getGuessCity().subscribe(res => { 53 | this.latitude = res.latitude; 54 | this.longitude = res.longitude; 55 | this.geohash = res.latitude + ',' + res.longitude; 56 | this.params = { geohash: this.geohash }; 57 | this.getPoisGeohash(); 58 | this.getMsiteFoodTypes(); 59 | this.getShopList(); 60 | }); 61 | } 62 | } 63 | 64 | getCategoryId(url) { 65 | const urlData = decodeURIComponent(url.split('=')[1].replace('&target_name', '')); 66 | if (/restaurant_category_id/gi.test(urlData)) { 67 | return JSON.parse(urlData).restaurant_category_id.id; 68 | } else { 69 | return ''; 70 | } 71 | } 72 | 73 | getPoisGeohash() { 74 | this.dataService.getPoisGeohash(this.geohash).subscribe(res => { 75 | this.addressTitle = res.name; 76 | this.hasGetData = true; 77 | }); 78 | } 79 | 80 | getMsiteFoodTypes() { 81 | this.dataService.getMsiteFoodTypes(this.geohash).subscribe(res => { 82 | const resArr = [...res]; 83 | this.foodTypes = this.spliceArray(resArr, 8); 84 | }); 85 | } 86 | getShopList() { 87 | this.dataService.getShopList(this.latitude, this.longitude, this.offset, this.restaurantCategoryId).subscribe(res => { 88 | if (res.length < 20) { 89 | this.touchend = true; 90 | } 91 | this.shopList = [...this.shopList, ...res]; 92 | this.showLoading = false; 93 | this.preventRepeatReuqest = false; 94 | }); 95 | } 96 | spliceArray(array: any[], spliceLength: number) { 97 | const length: number = array.length; 98 | const foodArr: any[] = []; 99 | for (let i = 0, j = 0; i < length; i += spliceLength, j++) { 100 | foodArr[j] = array.splice(0, spliceLength); 101 | } 102 | return foodArr; 103 | } 104 | 105 | toSearch() { 106 | this.router.navigateByUrl('/tabs/search?geohash=' + this.geohash); 107 | } 108 | 109 | loaderMore(event: any) { 110 | if (this.touchend) { 111 | event.target.disabled = true; 112 | return; 113 | } 114 | if (this.preventRepeatReuqest) { 115 | return; 116 | } 117 | this.offset += 20; 118 | this.showLoading = true; 119 | this.preventRepeatReuqest = true; 120 | this.getShopList(); 121 | event.target.complete(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/app/profile/profile.page.scss: -------------------------------------------------------------------------------- 1 | @import "../../style/mixin.scss"; 2 | @import "../../style/common.scss"; 3 | .profile-number{ 4 | display:flex; 5 | align-items: center; 6 | background:$blue; 7 | padding: .8rem 1rem; 8 | .privateImage{ 9 | display:inline-block; 10 | @include wh(4.1rem,4.1rem); 11 | border-radius:50%; 12 | vertical-align:middle; 13 | .privateImage-svg{ 14 | background:$fc; 15 | border-radius:50%; 16 | @include wh(4.1rem,4.1rem); 17 | } 18 | } 19 | .user-info{ 20 | margin-left:.8rem; 21 | -webkit-box-flex: 1; 22 | -ms-flex-positive: 1; 23 | flex-grow: 1; 24 | p{ 25 | font-weight:700; 26 | @include sc(1rem,$fc); 27 | .user-icon{ 28 | @include wh(0.83rem,1.25rem); 29 | display:inline-block; 30 | vertical-align:middle; 31 | line-height:1.25rem; 32 | .icon-mobile{ 33 | @include wh(100%,100%); 34 | } 35 | } 36 | .icon-mobile-number{ 37 | display:inline-block; 38 | @include sc(.9rem,$fc); 39 | margin-left: .5rem; 40 | vertical-align: middle; 41 | } 42 | } 43 | 44 | } 45 | } 46 | .info-data{ 47 | width:100%; 48 | background:$fc; 49 | box-sizing: border-box; 50 | ul{ 51 | .info-data-link{ 52 | float:left; 53 | width:33.33%; 54 | border-right:1px solid #f1f1f1; 55 | span{ 56 | display:block; 57 | width:100%; 58 | text-align:center; 59 | } 60 | .info-data-top{ 61 | @include sc(.92rem,#333); 62 | padding: 1.5rem 0 .75rem; 63 | b{ 64 | display:inline-block; 65 | @include sc(2rem,#f90); 66 | font-weight:700; 67 | line-height:1.67rem; 68 | font-family: Helvetica Neue,Tahoma; 69 | } 70 | } 71 | .info-data-bottom{ 72 | @include sc(.95rem,#666); 73 | font-weight:400; 74 | padding-bottom:.453333rem; 75 | 76 | } 77 | } 78 | .info-data-link:nth-of-type(2){ 79 | .info-data-top{ 80 | b{ 81 | color:#ff5f3e; 82 | } 83 | } 84 | 85 | } 86 | .info-data-link:nth-of-type(3){ 87 | border:0; 88 | .info-data-top{ 89 | b{ 90 | color:#6ac20b; 91 | } 92 | } 93 | } 94 | } 95 | } 96 | .profile-1reTe{ 97 | margin-top:.67rem; 98 | background:$fc; 99 | .myorder{ 100 | padding-left:1rem; 101 | display:flex; 102 | align-items: center; 103 | aside{ 104 | @include wh(1.16rem,1.16rem); 105 | margin-right:1.5rem; 106 | display:flex; 107 | align-items: center; 108 | svg{ 109 | @include wh(100%,100%); 110 | } 111 | } 112 | .myorder-div{ 113 | width:100%; 114 | border-bottom:1px solid #f1f1f1; 115 | padding: .8rem .5rem .8rem 0; 116 | @include sc(1.16rem,#333); 117 | display:flex; 118 | justify-content:space-between; 119 | span{ 120 | display:block; 121 | } 122 | .myorder-divsvg{ 123 | @include wh(.78rem,.78rem); 124 | svg{ 125 | @include wh(100%,100%); 126 | } 127 | } 128 | } 129 | } 130 | .myorder:nth-of-type(3) .myorder-div{ 131 | border:0; 132 | } 133 | } 134 | .profile-exit { 135 | line-height: 3rem; 136 | text-align: center; 137 | background-color: #fff; 138 | margin-top: 1.5rem; 139 | font-size: 1rem; 140 | .btn-exit { 141 | color: #ff5f3e; 142 | } 143 | } --------------------------------------------------------------------------------