├── src ├── assets │ └── .gitkeep ├── app │ ├── lazyload │ │ ├── index.ts │ │ ├── utils.ts │ │ ├── constants.ts │ │ ├── lazyload-image.module.ts │ │ ├── rect.ts │ │ ├── scroll-listener.ts │ │ ├── lazyload-image.directive.ts │ │ └── lazyload-image.ts │ ├── dialog │ │ ├── dialog.scss │ │ ├── dialog.html │ │ └── dialog.ts │ ├── danmus │ │ ├── danmu-item.html │ │ ├── danmu-item.scss │ │ └── danmu-item.ts │ ├── fullpage │ │ ├── index.ts │ │ ├── mnFullpage.module.ts │ │ ├── mnFullpage.service.ts │ │ ├── mnFullpage.directive.ts │ │ └── mnFullpage-options.class.ts │ ├── shared │ │ ├── shared.module.ts │ │ └── app.service.ts │ ├── lazyload-background │ │ ├── lazyload-image.ts │ │ └── lazyload-background.ts │ ├── app.module.ts │ ├── app.component.html │ ├── app.component.scss │ └── app.component.ts ├── favicon.ico ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── tsconfig.app.json ├── tsconfig.spec.json ├── main.ts ├── ngsw-config.json ├── typings.d.ts ├── styles.scss ├── index.html ├── test.ts └── polyfills.ts ├── meepo_hunli ├── install.php ├── uninstall.php ├── upgrade.php ├── developer.cer ├── template │ └── mobile │ │ ├── favicon.ico │ │ ├── ngsw.json │ │ ├── index.html │ │ └── 3rdpartylicenses.txt ├── module.php ├── manifest.xml ├── index.php └── site.php ├── service ├── index.js ├── nodemon.json ├── src │ ├── main.ts │ ├── database.module.ts │ ├── app.module.ts │ ├── database.providers.ts │ ├── hunli_discuss.module.ts │ ├── hunli_discuss.providers.ts │ ├── hunli_discuss.entity.ts │ ├── app.controller.ts │ └── hunli_discuss.service.ts ├── .gitignore ├── tsconfig.json ├── package.json ├── tslint.json └── README.md ├── .gitmodules ├── tslint.json ├── e2e ├── app.po.ts ├── tsconfig.e2e.json └── app.e2e-spec.ts ├── .editorconfig ├── tsconfig.json ├── .gitignore ├── protractor.conf.js ├── karma.conf.js ├── README.md ├── .angular-cli.json └── package.json /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /meepo_hunli/install.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |
6 | 7 |
8 | 9 | -------------------------------------------------------------------------------- /service/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { ApplicationModule } from './app.module'; 3 | 4 | async function bootstrap() { 5 | const app = await NestFactory.create(ApplicationModule); 6 | await app.listen(3000); 7 | } 8 | bootstrap(); 9 | -------------------------------------------------------------------------------- /e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /service/.gitignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # IDE 5 | /.idea 6 | /.awcache 7 | /.vscode 8 | 9 | # misc 10 | npm-debug.log 11 | 12 | # example 13 | /quick-start 14 | 15 | # tests 16 | /test 17 | /coverage 18 | /.nyc_output 19 | 20 | # dist 21 | /dist -------------------------------------------------------------------------------- /service/src/database.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { databaseProviders } from './database.providers'; 3 | 4 | @Module({ 5 | components: [...databaseProviders], 6 | exports: [...databaseProviders], 7 | }) 8 | export class DatabaseModule { } 9 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "module": "es2015", 7 | "types": [] 8 | }, 9 | "exclude": [ 10 | "test.ts", 11 | "**/*.spec.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/app/lazyload/lazyload-image.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { LazyLoadImageDirective } from './lazyload-image.directive'; 3 | 4 | @NgModule({ 5 | declarations: [LazyLoadImageDirective], 6 | exports: [LazyLoadImageDirective] 7 | }) 8 | export class LazyLoadImageModule { } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /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 | "types": [ 9 | "jasmine", 10 | "jasminewd2", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /service/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { AppController, AppGeteway } from './app.controller'; 3 | import { HunliDiscussModule } from './hunli_discuss.module'; 4 | 5 | @Module({ 6 | imports: [HunliDiscussModule], 7 | controllers: [AppController], 8 | components: [AppGeteway], 9 | }) 10 | export class ApplicationModule { } 11 | -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | 3 | describe('meepo-hunli-worker 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.getParagraphText()).toEqual('Welcome to app!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /src/app/fullpage/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Meiblorn (Vadim Fedorenko) on 15/05/16. 3 | */ 4 | 5 | export { MnFullpageModule } from './mnFullpage.module'; 6 | export { MnFullpageDirective } from './mnFullpage.directive'; 7 | export { MnFullpageOptions } from './mnFullpage-options.class'; 8 | export { MnFullpageService } from './mnFullpage.service'; 9 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "node" 11 | ] 12 | }, 13 | "files": [ 14 | "test.ts" 15 | ], 16 | "include": [ 17 | "**/*.spec.ts", 18 | "**/*.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /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 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/out-tsc", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "target": "es5", 11 | "typeRoots": [ 12 | "node_modules/@types" 13 | ], 14 | "lib": [ 15 | "es2017", 16 | "dom" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/app/dialog/dialog.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 填写联系方式 4 | 关闭 5 |
6 | 7 | 姓名 8 | 9 | 10 | 电话 11 | 12 |
-------------------------------------------------------------------------------- /service/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": false, 5 | "noImplicitAny": false, 6 | "removeComments": true, 7 | "noLib": false, 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "target": "es6", 11 | "sourceMap": true, 12 | "allowJs": true, 13 | "outDir": "./dist" 14 | }, 15 | "include": [ 16 | "src/**/*" 17 | ], 18 | "exclude": [ 19 | "node_modules", 20 | "**/*.spec.ts" 21 | ] 22 | } -------------------------------------------------------------------------------- /service/src/database.providers.ts: -------------------------------------------------------------------------------- 1 | import { createConnection } from 'typeorm'; 2 | 3 | export const databaseProviders = [ 4 | { 5 | provide: 'DbConnectionToken', 6 | useFactory: async () => await createConnection({ 7 | type: 'mysql', 8 | host: 'mysql host', 9 | port: 3306, 10 | username: 'username', 11 | password: 'password', 12 | database: 'some data base', 13 | entities: [ 14 | __dirname + '/../**/*.entity{.ts,.js}', 15 | ], 16 | }), 17 | }, 18 | ]; 19 | -------------------------------------------------------------------------------- /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 | 8 | if (environment.production) { 9 | enableProdMode(); 10 | } else { 11 | window['UserInfo'] = () => { }; 12 | window['wx'] = { 13 | ready: () => { } 14 | }; 15 | } 16 | 17 | platformBrowserDynamic().bootstrapModule(AppModule) 18 | .catch(err => console.log(err)); 19 | -------------------------------------------------------------------------------- /service/src/hunli_discuss.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { DatabaseModule } from './database.module'; 3 | import { HunliDiscussProviders } from './hunli_discuss.providers'; 4 | import { HunliDiscussService, HunliFuyueService } from './hunli_discuss.service'; 5 | 6 | @Module({ 7 | imports: [DatabaseModule], 8 | components: [ 9 | ...HunliDiscussProviders, 10 | HunliDiscussService, 11 | HunliFuyueService, 12 | ], 13 | exports: [HunliDiscussService, HunliFuyueService], 14 | }) 15 | export class HunliDiscussModule { } -------------------------------------------------------------------------------- /src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { AppService } from './app.service'; 5 | import { ReactiveFormsModule, FormsModule } from '@angular/forms'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | ReactiveFormsModule, 10 | FormsModule, 11 | CommonModule 12 | ], 13 | exports: [ 14 | ReactiveFormsModule, 15 | FormsModule 16 | ], 17 | declarations: [], 18 | providers: [ 19 | AppService 20 | ] 21 | }) 22 | export class SharedModule { } 23 | -------------------------------------------------------------------------------- /src/ngsw-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": "/index.html", 3 | "assetGroups": [{ 4 | "name": "app", 5 | "installMode": "prefetch", 6 | "resources": { 7 | "files": [ 8 | "/favicon.ico", 9 | "/index.html" 10 | ], 11 | "versionedFiles": [ 12 | "/*.bundle.css", 13 | "/*.bundle.js", 14 | "/*.chunk.js" 15 | ] 16 | } 17 | }, { 18 | "name": "assets", 19 | "installMode": "lazy", 20 | "updateMode": "prefetch", 21 | "resources": { 22 | "files": [ 23 | "/assets/**" 24 | ] 25 | } 26 | }] 27 | } -------------------------------------------------------------------------------- /service/src/hunli_discuss.providers.ts: -------------------------------------------------------------------------------- 1 | import { Connection, Repository } from 'typeorm'; 2 | import { ImsImeeposHunliDiscuss, ImsImeeposHunliFuyue } from './hunli_discuss.entity'; 3 | 4 | export const HunliDiscussProviders = [ 5 | { 6 | provide: 'HunliDiscussRepositoryToken', 7 | useFactory: (connection: Connection) => connection.getRepository(ImsImeeposHunliDiscuss), 8 | inject: ['DbConnectionToken'], 9 | }, 10 | { 11 | provide: 'HunliFuyueRepositoryToken', 12 | useFactory: (connection: Connection) => connection.getRepository(ImsImeeposHunliFuyue), 13 | inject: ['DbConnectionToken'], 14 | }, 15 | ]; -------------------------------------------------------------------------------- /src/app/fullpage/mnFullpage.module.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Meiblorn (Vadim Fedorenko) on 15/05/16. 3 | */ 4 | 5 | import { ModuleWithProviders, NgModule } from '@angular/core'; 6 | import { MnFullpageService } from './mnFullpage.service'; 7 | import { MnFullpageDirective } from './mnFullpage.directive'; 8 | 9 | @NgModule({ 10 | declarations: [ MnFullpageDirective ], 11 | exports: [ MnFullpageDirective ] 12 | }) 13 | export class MnFullpageModule { 14 | 15 | public static forRoot(): ModuleWithProviders { 16 | return { 17 | ngModule: MnFullpageModule, 18 | providers: [ MnFullpageService ] 19 | }; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | 7 | declare var $: any; 8 | declare var UserInfo: { 9 | openid: string; 10 | avatar: string; 11 | nickname: string; 12 | } 13 | 14 | declare var wx: any; 15 | declare interface jssdkconfig { 16 | appId: string; 17 | nonceStr: string; 18 | timestamp: number; 19 | signature: string; 20 | debug: boolean; 21 | jsApiList: string[]; 22 | } 23 | declare var jssdkconfig: jssdkconfig; 24 | declare interface sysinfo { 25 | siteurl: string; 26 | uniacid: number; 27 | acid: number; 28 | siteroot: string; 29 | attachurl: string; 30 | MODULE_URL: string; 31 | } 32 | declare var sysinfo: sysinfo; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /service/node_modules 8 | /meepo_hunli/template 9 | 10 | 11 | # dependencies 12 | /node_modules 13 | *.mp3 14 | *.mp4 15 | *.jpg 16 | *.png 17 | 18 | # IDEs and editors 19 | /.idea 20 | .project 21 | .classpath 22 | .c9/ 23 | *.launch 24 | .settings/ 25 | *.sublime-workspace 26 | 27 | # IDE - VSCode 28 | .vscode/* 29 | !.vscode/settings.json 30 | !.vscode/tasks.json 31 | !.vscode/launch.json 32 | !.vscode/extensions.json 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | testem.log 41 | /typings 42 | 43 | # e2e 44 | /e2e/*.js 45 | /e2e/*.map 46 | 47 | # System Files 48 | .DS_Store 49 | Thumbs.db 50 | -------------------------------------------------------------------------------- /service/src/hunli_discuss.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; 2 | 3 | @Entity() 4 | export class ImsImeeposHunliDiscuss { 5 | @PrimaryGeneratedColumn() 6 | id: number; 7 | 8 | @Column({ length: 640 }) 9 | avatar: string; 10 | 11 | @Column() content: string; 12 | 13 | @Column() openid: string; 14 | 15 | @Column() create_time: number; 16 | } 17 | 18 | 19 | @Entity() 20 | export class ImsImeeposHunliFuyue { 21 | @PrimaryGeneratedColumn() 22 | id: number; 23 | 24 | @Column({ length: 640 }) 25 | avatar: string; 26 | 27 | @Column() content: string; 28 | 29 | @Column() openid: string; 30 | 31 | @Column() realname: string; 32 | @Column() mobile: string; 33 | @Column() nickname: string; 34 | 35 | @Column() create_time: number; 36 | } -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './e2e/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nest-typescript-starter", 3 | "version": "1.0.0", 4 | "description": "Nest TypeScript starter repository", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "node index.js", 8 | "start:watch": "nodemon", 9 | "prestart:prod": "tsc", 10 | "start:prod": "node dist/main.js" 11 | }, 12 | "dependencies": { 13 | "@nestjs/common": "^4.5.9", 14 | "@nestjs/core": "^4.5.10", 15 | "@nestjs/microservices": "^4.5.8", 16 | "@nestjs/testing": "^4.5.5", 17 | "@nestjs/websockets": "^4.5.8", 18 | "@types/socket.io": "^1.4.31", 19 | "mysql": "^2.15.0", 20 | "redis": "^2.7.1", 21 | "reflect-metadata": "^0.1.12", 22 | "rxjs": "^5.5.6", 23 | "socket.io": "^2.0.4", 24 | "typeorm": "^0.1.11", 25 | "typescript": "^2.6.2" 26 | }, 27 | "devDependencies": { 28 | "@types/node": "^9.3.0", 29 | "nodemon": "^1.14.1", 30 | "ts-node": "^4.1.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | @import "~normalize.css"; 2 | @import "~weui"; 3 | body, 4 | html, 5 | app-root { 6 | display: block; 7 | height: 100%; 8 | overflow: hidden; 9 | } 10 | 11 | .audio-control { 12 | position: fixed; 13 | top: 50px; 14 | right: 10px; 15 | z-index: 10; 16 | background: rgba(0, 0, 0, .8); 17 | border-radius: 50%; 18 | display: flex; 19 | flex-direction: column; 20 | justify-content: center; 21 | align-content: center; 22 | animation: rotate .8s; 23 | animation-iteration-count: 9999; 24 | overflow: hidden; 25 | img { 26 | width: 50px; 27 | height: 50px; 28 | } 29 | } 30 | 31 | @keyframes rotate { 32 | 0% { 33 | transform: rotate(0deg); 34 | } 35 | 25% { 36 | transform: rotate(90deg); 37 | } 38 | } -------------------------------------------------------------------------------- /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/cli'], 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/cli/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | reports: [ 'html', 'lcovonly' ], 20 | fixWebpackSourcePaths: true 21 | }, 22 | angularCli: { 23 | environment: 'dev' 24 | }, 25 | reporters: ['progress', 'kjhtml'], 26 | port: 9876, 27 | colors: true, 28 | logLevel: config.LOG_INFO, 29 | autoWatch: true, 30 | browsers: ['Chrome'], 31 | singleRun: false 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /src/app/danmus/danmu-item.scss: -------------------------------------------------------------------------------- 1 | .danmu-item { 2 | position: fixed; 3 | height: 44px; 4 | background: rgba(0, 0, 0, .5); 5 | overflow: visible; 6 | z-index: 9; 7 | width: auto; 8 | color: #fff; 9 | padding: 0 10px; 10 | border-radius: 10px; 11 | max-width: 10em; 12 | min-width: 10em; 13 | .danmu-item-wrap { 14 | height: 100%; 15 | display: flex; 16 | flex-direction: row; 17 | align-items: center; 18 | .danmu-item-avatar { 19 | height: 100%; 20 | display: flex; 21 | flex-direction: column; 22 | justify-content: center; 23 | align-items: center; 24 | height: 3em; 25 | min-width: 3em; 26 | img { 27 | height: 2em; 28 | width: 2em; 29 | border-radius: 50%; 30 | } 31 | } 32 | .danmu-item-content { 33 | flex: 1; 34 | align-items: center; 35 | justify-content: center; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 杨明明&闫聪玲-我们要结婚啦 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | {php echo register_jssdk()} 20 |
21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/app/dialog/dialog.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; 2 | import { ViewEncapsulation } from '@angular/core'; 3 | 4 | export interface DialogInput { 5 | realname: string; 6 | mobile: string; 7 | } 8 | @Component({ 9 | selector: 'dialog', 10 | templateUrl: './dialog.html', 11 | styleUrls: ['./dialog.scss'], 12 | encapsulation: ViewEncapsulation.None 13 | }) 14 | export class DialogComponent implements OnInit { 15 | @Input() model: DialogInput = { 16 | realname: '', 17 | mobile: '' 18 | }; 19 | @Output() onCancel: EventEmitter = new EventEmitter(); 20 | @Output() modelChange: EventEmitter = new EventEmitter(); 21 | 22 | constructor() { } 23 | 24 | ngOnInit() { } 25 | 26 | inputRealname(e) { 27 | this.model.realname = e.target.value; 28 | this.modelChange.emit(this.model); 29 | } 30 | 31 | inputMobile(e) { 32 | this.model.mobile = e.target.value; 33 | this.modelChange.emit(this.model); 34 | } 35 | 36 | cancel() { 37 | this.onCancel.emit(); 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /meepo_hunli/manifest.xml: -------------------------------------------------------------------------------- 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 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /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/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare const __karma__: any; 17 | declare const require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /meepo_hunli/index.php: -------------------------------------------------------------------------------- 1 | model('mc'); 9 | 10 | $randomContents = [ 11 | '恭喜发财', 12 | '新婚大吉', 13 | '新娘漂亮啊', 14 | '牛逼了', 15 | '飞起飞起', 16 | '明哥带我飞', 17 | '必须亲临', 18 | '人生啊', 19 | '羡慕嫉妒', 20 | '新婚愉快', 21 | '明总霸气', 22 | '姐姐好漂亮', 23 | '姐姐想赵丽颖啊', 24 | '赵丽颖', 25 | '哈哈哈,有才', 26 | '红包拿来', 27 | '吸气洋洋', 28 | '发红包', 29 | '天下竟有如此美人', 30 | '霸气不解释', 31 | '背景不错', 32 | '这发型亮了', 33 | '德信智能家具贺!', 34 | '恩爱到白头', 35 | '放开那姑娘!', 36 | '永结同心!', 37 | '好好好', 38 | '胜记科技前来恭贺!', 39 | '放开那姑娘+1', 40 | '放开那姑娘+1', 41 | ]; 42 | 43 | $fanss = array(); 44 | 45 | foreach ($list as $key=>$li) { 46 | $userinfo = mc_fansinfo($li['openid']); 47 | $data = array(); 48 | $data['content'] = $randomContents[$key]; 49 | $data['avatar'] = $userinfo['avatar']; 50 | $data['create_time'] = time(); 51 | $data['openid'] = $_W['openid']; 52 | pdo_insert('imeepos_hunli_discuss',$data); 53 | $fanss[] = $data; 54 | } 55 | 56 | die(json_encode($fanss)); 57 | -------------------------------------------------------------------------------- /service/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "jsRules": { 7 | "no-unused-expression": true 8 | }, 9 | "rules": { 10 | "eofline": false, 11 | "quotemark": [ 12 | true, 13 | "single" 14 | ], 15 | "indent": false, 16 | "member-access": [ 17 | false 18 | ], 19 | "ordered-imports": [ 20 | false 21 | ], 22 | "max-line-length": [ 23 | 150 24 | ], 25 | "member-ordering": [ 26 | false 27 | ], 28 | "curly": false, 29 | "interface-name": [ 30 | false 31 | ], 32 | "array-type": [ 33 | false 34 | ], 35 | "no-empty-interface": false, 36 | "no-empty": false, 37 | "arrow-parens": false, 38 | "object-literal-sort-keys": false, 39 | "no-unused-expression": false, 40 | "max-classes-per-file": [ 41 | false 42 | ], 43 | "variable-name": [ 44 | false 45 | ], 46 | "one-line": [ 47 | false 48 | ], 49 | "one-variable-per-declaration": [ 50 | false 51 | ] 52 | }, 53 | "rulesDirectory": [] 54 | } -------------------------------------------------------------------------------- /meepo_hunli/site.php: -------------------------------------------------------------------------------- 1 | getRealUrl(); 22 | if ($url !== $_W['siteurl']) { 23 | header("location:" . $url); 24 | exit(); 25 | } 26 | include $this->template('index'); 27 | } 28 | 29 | public function doWebIndex() 30 | { 31 | global $_W, $_GPC; 32 | include $this->template('index'); 33 | } 34 | 35 | public function doMobileUpdate() 36 | { 37 | 38 | } 39 | 40 | public function getRealUrl() 41 | { 42 | $protocol = (!empty($_SERVER[HTTPS]) && $_SERVER[HTTPS] !== off || $_SERVER[SERVER_PORT] == 443) ? "https://" : "http://"; 43 | $url = $protocol . $_SERVER[HTTP_HOST] . $_SERVER[REQUEST_URI]; 44 | preg_match("/.*?(\&from=.*)/", $url, $maches); 45 | $url = str_replace($maches[1], '', $url); 46 | return $url; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 婚礼互动 2 | 3 | > mysql+nestjs+typeorm+mysql+angular 小项目自用,socket实时互动 4 | 5 | - [demo](https://meepo.com.cn/app/index.php?i=2&c=entry&do=index&m=meepo_hunli) 6 | 7 | - 微信端 8 | 9 | ```sh 10 | git clone https://github.com/meepobrother/meepo-hunli.git 11 | yarn 12 | yarn start 13 | ``` 14 | 15 | - 服务器 16 | ```sh 17 | cd service && yarn && yarn start 18 | ``` 19 | 20 | 21 | - [数据库配置文件](service/src/database.providers.ts) 22 | 23 | ```ts 24 | // 数据库配置 25 | import { createConnection } from 'typeorm'; 26 | 27 | export const databaseProviders = [ 28 | { 29 | provide: 'DbConnectionToken', 30 | useFactory: async () => await createConnection({ 31 | type: 'mysql', 32 | host: 'mysql host', // 地址 33 | port: 3306,// 端口号 34 | username: 'username',// 用户名 35 | password: 'password',// 密码 36 | database: 'some data base',// 数据库 37 | entities: [ 38 | __dirname + '/../**/*.entity{.ts,.js}', 39 | ], 40 | }), 41 | }, 42 | ]; 43 | 44 | 45 | ``` 46 | 47 | - [图片地址配置](src/app/app.module.ts) 48 | ```ts 49 | import { BASE_SRC } from './lazyload-background/lazyload-background'; 50 | @NgModule({ 51 | providers: [ 52 | { 53 | provide: APP_BASE_HREF, 54 | useValue: './' 55 | }, 56 | { 57 | provide: BASE_SRC, 58 | useValue: '../addons/meepo_hunli/template/mobile/' // 图片服务器地址 59 | } 60 | ] 61 | }) 62 | export class AppModule { } 63 | 64 | ``` -------------------------------------------------------------------------------- /meepo_hunli/template/mobile/ngsw.json: -------------------------------------------------------------------------------- 1 | { 2 | "configVersion": 1, 3 | "index": "/index.html", 4 | "assetGroups": [ 5 | { 6 | "name": "app", 7 | "installMode": "prefetch", 8 | "updateMode": "prefetch", 9 | "urls": [ 10 | "/favicon.ico", 11 | "/index.html", 12 | "/inline.2505c5ad7efec7576dff.bundle.js", 13 | "/main.ee2a797dfde4b765cfc2.bundle.js", 14 | "/polyfills.55f013ac603c1bf4a514.bundle.js", 15 | "/scripts.8f822722eef5e52ce2c5.bundle.js", 16 | "/styles.8f26c4c9dd5dbd4d38b8.bundle.css" 17 | ], 18 | "patterns": [] 19 | }, 20 | { 21 | "name": "assets", 22 | "installMode": "lazy", 23 | "updateMode": "prefetch", 24 | "urls": [], 25 | "patterns": [] 26 | } 27 | ], 28 | "dataGroups": [], 29 | "hashTable": { 30 | "/inline.2505c5ad7efec7576dff.bundle.js": "9045b0a86e6500daf02d3d186d95dc0e3ed9803b", 31 | "/main.ee2a797dfde4b765cfc2.bundle.js": "5c10044aacd8336cade961438984e7f13fa725be", 32 | "/polyfills.55f013ac603c1bf4a514.bundle.js": "bbe96ec05c994458177b66689f1fc035aaeab13a", 33 | "/scripts.8f822722eef5e52ce2c5.bundle.js": "0ad94805c3076e6959974d04f3afcd078a642e46", 34 | "/styles.8f26c4c9dd5dbd4d38b8.bundle.css": "d3e4b92dc4d0ea2ec1305b5786ce6bacee7a23f8", 35 | "/favicon.ico": "84161b857f5c547e3699ddfbffc6d8d737542e01", 36 | "/index.html": "4c79ed0b5fd71acc414d82eae1f20bd60a0e3bcc" 37 | } 38 | } -------------------------------------------------------------------------------- /meepo_hunli/template/mobile/index.html: -------------------------------------------------------------------------------- 1 | 杨明明&闫聪玲-我们要结婚啦
{php echo register_jssdk()}
-------------------------------------------------------------------------------- /service/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Get, Controller } from '@nestjs/common'; 2 | import { WebSocketGateway, SubscribeMessage, WebSocketServer } from '@nestjs/websockets'; 3 | import { HunliDiscussService, HunliFuyueService } from './hunli_discuss.service'; 4 | 5 | @WebSocketGateway({ port: 1314 }) 6 | export class AppGeteway { 7 | @WebSocketServer() server; 8 | 9 | constructor(private hunli: HunliDiscussService, private fuyue: HunliFuyueService) { 10 | 11 | } 12 | 13 | @SubscribeMessage('hunli.discuss') 14 | async handelHunliDiscuss(sender, data) { 15 | const list = await this.hunli.findAll(); 16 | sender.emit('hunli.discuss', list); 17 | } 18 | 19 | @SubscribeMessage('hunli.discuss.add') 20 | async handelHunliDiscussAdd(sender, data) { 21 | const item = await this.hunli.addOne(data); 22 | const list = await this.hunli.findAll(); 23 | sender.broadcast.emit('hunli.discuss.add', data); 24 | sender.emit('hunli.discuss.add', data); 25 | } 26 | 27 | @SubscribeMessage('hunli.fuyue') 28 | async handelHunliFuyue(sender, data) { 29 | const list = await this.fuyue.findAll(); 30 | sender.emit('hunli.fuyue', list); 31 | } 32 | 33 | @SubscribeMessage('hunli.fuyue.add') 34 | async handelHunliFuyueAdd(sender, data) { 35 | const item = await this.fuyue.addOne(data); 36 | if (item) { 37 | const list = await this.fuyue.findAll(); 38 | sender.broadcast.emit('hunli.fuyue.add', data); 39 | sender.emit('hunli.fuyue.add', data); 40 | } 41 | } 42 | } 43 | 44 | @Controller() 45 | export class AppController { 46 | @Get() 47 | root(): string { 48 | return 'Hello World!'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/app/lazyload/rect.ts: -------------------------------------------------------------------------------- 1 | export class Rect { 2 | static empty: Rect = new Rect(0, 0, 0, 0); 3 | 4 | left: number; 5 | top: number; 6 | right: number; 7 | bottom: number; 8 | 9 | constructor(left: number, top: number, right: number, bottom: number) { 10 | this.left = left; 11 | this.top = top; 12 | this.right = right; 13 | this.bottom = bottom; 14 | } 15 | 16 | static fromElement(element: HTMLElement): Rect { 17 | const { left, top, right, bottom } = element.getBoundingClientRect(); 18 | return new Rect(left, top, right, bottom); 19 | } 20 | 21 | static fromWindow(_window: Window): Rect { 22 | return new Rect(0, 0, _window.innerWidth, _window.innerHeight); 23 | } 24 | 25 | inflate(inflateBy: number) { 26 | this.left -= inflateBy; 27 | this.top -= inflateBy; 28 | this.right += inflateBy; 29 | this.bottom += inflateBy; 30 | } 31 | 32 | intersectsWith(rect: Rect): boolean { 33 | return (rect.left < this.right) && 34 | (this.left < rect.right) && 35 | (rect.top < this.bottom) && 36 | (this.top < rect.bottom); 37 | } 38 | 39 | getIntersectionWith(rect: Rect): Rect { 40 | const left = Math.max(this.left, rect.left); 41 | const top = Math.max(this.top, rect.top); 42 | const right = Math.min(this.right, rect.right); 43 | const bottom = Math.min(this.bottom, rect.bottom); 44 | 45 | if (right >= left && bottom >= top) { 46 | return new Rect(left, top, right, bottom); 47 | } else { 48 | return Rect.empty; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/app/lazyload/scroll-listener.ts: -------------------------------------------------------------------------------- 1 | import 'rxjs/add/operator/startWith'; 2 | import 'rxjs/add/operator/sampleTime'; 3 | import 'rxjs/add/operator/share'; 4 | import 'rxjs/add/observable/empty'; 5 | import { Observable } from 'rxjs/Observable'; 6 | import { isWindowDefined } from './utils'; 7 | 8 | const scrollListeners = new WeakMap>(); 9 | 10 | export function sampleObservable(obs: Observable, scheduler?: any) { 11 | return obs 12 | .sampleTime(100, scheduler) 13 | .share() 14 | .startWith(''); 15 | } 16 | 17 | // Only create one scroll listener per target and share the observable. 18 | // Typical, there will only be one observable per application 19 | export const getScrollListener = (scrollTarget): Observable => { 20 | if (!scrollTarget || typeof scrollTarget.addEventListener !== 'function') { 21 | if (isWindowDefined()) { 22 | console.warn('`addEventListener` on ' + scrollTarget + ' (scrollTarget) is not a function. Skipping this target'); 23 | } 24 | return Observable.empty(); 25 | } 26 | if (scrollListeners.has(scrollTarget)) { 27 | return scrollListeners.get(scrollTarget); 28 | } 29 | 30 | const srollEvent = Observable.create(observer => { 31 | const eventName = 'scroll'; 32 | const handler = event => observer.next(event); 33 | const options = { passive: true, capture: false }; 34 | scrollTarget.addEventListener(eventName, handler, options); 35 | return () => scrollTarget.removeEventListener(eventName, handler, options); 36 | }); 37 | 38 | const listener = sampleObservable(srollEvent); 39 | scrollListeners.set(scrollTarget, listener); 40 | return listener; 41 | }; 42 | -------------------------------------------------------------------------------- /src/app/lazyload-background/lazyload-image.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Directive, Input, AfterViewInit, 3 | ElementRef, Renderer2, OnInit, 4 | InjectionToken, Injector, OnDestroy 5 | } from '@angular/core'; 6 | import { BASE_SRC } from './lazyload-background'; 7 | import { isDevMode } from '@angular/core'; 8 | @Directive({ selector: '[lazyload]' }) 9 | export class LazyloadDirective implements OnInit, OnDestroy, AfterViewInit { 10 | private _imageSrc: string; 11 | private _imageLazySrc: string; 12 | private _imageIndex: number; 13 | private _isLoaded: boolean = false; 14 | private _subser: any; 15 | @Input() 16 | set lazyload(img: string) { 17 | this._imageSrc = img; 18 | this._imageLazySrc = `${this.src}assets/images/default.png`; 19 | } 20 | defaultImage: any; 21 | src: string; 22 | constructor( 23 | private render: Renderer2, 24 | private ele: ElementRef, 25 | private injector: Injector 26 | ) { 27 | if (isDevMode()) { 28 | this.src = './'; 29 | } else { 30 | this.src = this.injector.get(BASE_SRC, './') as string; 31 | } 32 | } 33 | 34 | ngOnDestroy() { 35 | this._subser && this._subser.unsubscribe(); 36 | } 37 | 38 | ngOnInit() { 39 | this.render.setAttribute(this.ele.nativeElement, 'src', this._imageLazySrc); 40 | } 41 | 42 | createLazy() { 43 | const img = new Image(); 44 | img.src = this._imageSrc; 45 | img.onload = () => { 46 | this.render.setAttribute(this.ele.nativeElement, 'src', this._imageSrc); 47 | this._isLoaded = true; 48 | }; 49 | } 50 | 51 | ngAfterViewInit() { 52 | this.createLazy(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "project": { 4 | "name": "meepo-hunli-worker" 5 | }, 6 | "apps": [ 7 | { 8 | "root": "src", 9 | "outDir": "meepo_hunli/template/mobile/", 10 | "assets": [ 11 | "assets", 12 | "favicon.ico" 13 | ], 14 | "index": "index.html", 15 | "main": "main.ts", 16 | "polyfills": "polyfills.ts", 17 | "test": "test.ts", 18 | "tsconfig": "tsconfig.app.json", 19 | "testTsconfig": "tsconfig.spec.json", 20 | "prefix": "app", 21 | "styles": [ 22 | "styles.scss" 23 | ], 24 | "scripts": [ 25 | "../node_modules/jquery/dist/jquery.js", 26 | "../node_modules/fullpage.js/dist/jquery.fullpage.js", 27 | "../node_modules/socket.io-client/dist/socket.io.js" 28 | ], 29 | "environmentSource": "environments/environment.ts", 30 | "environments": { 31 | "dev": "environments/environment.ts", 32 | "prod": "environments/environment.prod.ts" 33 | }, 34 | "serviceWorker": true 35 | } 36 | ], 37 | "e2e": { 38 | "protractor": { 39 | "config": "./protractor.conf.js" 40 | } 41 | }, 42 | "lint": [ 43 | { 44 | "project": "src/tsconfig.app.json", 45 | "exclude": "**/node_modules/**" 46 | }, 47 | { 48 | "project": "src/tsconfig.spec.json", 49 | "exclude": "**/node_modules/**" 50 | }, 51 | { 52 | "project": "e2e/tsconfig.e2e.json", 53 | "exclude": "**/node_modules/**" 54 | } 55 | ], 56 | "test": { 57 | "karma": { 58 | "config": "./karma.conf.js" 59 | } 60 | }, 61 | "defaults": { 62 | "styleExt": "css", 63 | "component": {} 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /service/src/hunli_discuss.service.ts: -------------------------------------------------------------------------------- 1 | import { Component, Inject } from '@nestjs/common'; 2 | import { Repository } from 'typeorm'; 3 | import { ImsImeeposHunliDiscuss, ImsImeeposHunliFuyue } from './hunli_discuss.entity'; 4 | 5 | @Component() 6 | export class HunliDiscussService { 7 | constructor( 8 | @Inject('HunliDiscussRepositoryToken') private readonly photoRepository: Repository 9 | ) { } 10 | 11 | async findAll(): Promise { 12 | return this.photoRepository.createQueryBuilder() 13 | .where({}) 14 | .orderBy('create_time', 'DESC') 15 | .getMany(); 16 | } 17 | 18 | async addOne(item: ImsImeeposHunliDiscuss): Promise { 19 | return await this.photoRepository.insert(item); 20 | } 21 | } 22 | 23 | @Component() 24 | export class HunliFuyueService { 25 | constructor( 26 | @Inject('HunliFuyueRepositoryToken') private readonly photoRepository: Repository 27 | ) { } 28 | 29 | async findAll(): Promise { 30 | return this.photoRepository.createQueryBuilder() 31 | .where({}) 32 | .orderBy('create_time', 'DESC') 33 | .getMany(); 34 | } 35 | 36 | async addOne(item: ImsImeeposHunliFuyue): Promise { 37 | const exist = await this.checkExist(item); 38 | if (exist) { 39 | return null; 40 | } 41 | return await this.photoRepository.insert(item); 42 | } 43 | 44 | async checkExist(item: ImsImeeposHunliFuyue): Promise { 45 | const exist = await this.photoRepository 46 | .createQueryBuilder() 47 | .where({ mobile: item.mobile }) 48 | .getOne(); 49 | return exist ? true : false; 50 | } 51 | } -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | import { APP_BASE_HREF } from '@angular/common'; 4 | import { HttpClientModule } from '@angular/common/http'; 5 | 6 | import { ServiceWorkerModule } from '@angular/service-worker'; 7 | import { AppComponent } from './app.component'; 8 | import { environment } from '../environments/environment'; 9 | import { MnFullpageModule } from './fullpage'; 10 | import { LazyLoadImageModule } from './lazyload'; 11 | import { LazyBackgroundDirective } from './lazyload-background/lazyload-background'; 12 | import { LazyloadDirective } from './lazyload-background/lazyload-image'; 13 | import { DialogComponent } from './dialog/dialog'; 14 | 15 | 16 | import { DanmuItemComponent } from './danmus/danmu-item'; 17 | import { NoticeBarModule } from 'ng-antd-mobile-notice-bar'; 18 | import { BASE_SRC } from './lazyload-background/lazyload-background'; 19 | import { ListModule, InputItemModule } from 'ng-antd-mobile'; 20 | @NgModule({ 21 | declarations: [ 22 | AppComponent, 23 | LazyBackgroundDirective, 24 | DanmuItemComponent, 25 | LazyloadDirective, 26 | DialogComponent 27 | ], 28 | imports: [ 29 | BrowserModule, 30 | ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }), 31 | LazyLoadImageModule, 32 | MnFullpageModule.forRoot(), 33 | HttpClientModule, 34 | NoticeBarModule, 35 | ListModule, 36 | InputItemModule 37 | ], 38 | providers: [ 39 | { 40 | provide: APP_BASE_HREF, 41 | useValue: './' 42 | }, 43 | { 44 | provide: BASE_SRC, 45 | useValue: '../addons/meepo_hunli/template/mobile/' 46 | } 47 | ], 48 | entryComponents: [DanmuItemComponent], 49 | bootstrap: [AppComponent] 50 | }) 51 | export class AppModule { } 52 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 本程序由杨明明开发自用,如有朋友需要,可以联系我哦! 4 | 5 |
6 |
嘉宾({{fuyues.length}})
7 | 8 |
9 |
10 | 11 |
12 |
13 |
14 |
15 |
16 | 17 | {{item.content}} 18 | 19 | 33 |
34 | 37 | 38 |
39 |
40 |

地址: 安阳市滑县万古镇棘马林村

41 |

电话: 42 | 13140415408 43 |

44 |

时间:农历22,阳历2月7号!

45 |
-------------------------------------------------------------------------------- /src/app/lazyload-background/lazyload-background.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Directive, Input, AfterViewInit, 3 | ElementRef, Renderer2, OnInit, 4 | InjectionToken, Injector, OnDestroy 5 | } from '@angular/core'; 6 | export const BASE_SRC = new InjectionToken('BASE_SRC'); 7 | @Directive({ selector: '[lazyBackground]' }) 8 | export class LazyBackgroundDirective implements OnInit, OnDestroy { 9 | private _imageSrc: string; 10 | private _imageLazySrc: string; 11 | private _imageIndex: number; 12 | private _isLoaded: boolean = false; 13 | private _subser: any; 14 | @Input() 15 | set lazyBackground(index: number) { 16 | this._imageIndex = index; 17 | this._imageSrc = `${this.src}assets/images/${index}.png`; 18 | this._imageLazySrc = `${this.src}assets/images/${index}.lazy.png`; 19 | } 20 | @Input() 21 | set nowIndex(index: any) { 22 | if (index) { 23 | this._subser = index.subscribe(res => { 24 | if (res === this._imageIndex) { 25 | !this._isLoaded && this.createLazy(this._imageSrc); 26 | } 27 | }); 28 | } 29 | } 30 | defaultImage: any; 31 | src: string; 32 | constructor( 33 | private render: Renderer2, 34 | private ele: ElementRef, 35 | private injector: Injector 36 | ) { 37 | this.src = this.injector.get(BASE_SRC, './') as string; 38 | } 39 | 40 | ngOnDestroy() { 41 | this._subser && this._subser.unsubscribe(); 42 | } 43 | 44 | ngOnInit() { 45 | this.render.setStyle(this.ele.nativeElement, 'background-image', `url(${this._imageLazySrc})`); 46 | } 47 | 48 | createLazy(image: string) { 49 | setTimeout(() => { 50 | const img = new Image(); 51 | img.src = image; 52 | img.onload = () => { 53 | this.render.setStyle(this.ele.nativeElement, 'background-image', `url(${image})`); 54 | this._isLoaded = true; 55 | }; 56 | }, 1000); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "meepo-hunli-worker", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "ng serve --open", 8 | "build": "ng build --prod --deploy-url ../addons/meepo_hunli/template/mobile/", 9 | "test": "ng test", 10 | "lint": "ng lint", 11 | "e2e": "ng e2e", 12 | "git": "git add . && git commit -m 'update to save' && git push origin master" 13 | }, 14 | "private": true, 15 | "dependencies": { 16 | "@angular-devkit/core": "^0.0.28", 17 | "@angular/animations": "^5.0.0", 18 | "@angular/cdk": "^5.1.0", 19 | "@angular/common": "^5.0.0", 20 | "@angular/compiler": "^5.0.0", 21 | "@angular/core": "^5.0.0", 22 | "@angular/forms": "^5.0.0", 23 | "@angular/http": "^5.0.0", 24 | "@angular/platform-browser": "^5.0.0", 25 | "@angular/platform-browser-dynamic": "^5.0.0", 26 | "@angular/router": "^5.0.0", 27 | "@angular/service-worker": "^5.0.0", 28 | "@types/socket.io-client": "^1.4.32", 29 | "classlist.js": "^1.1.20150312", 30 | "classnames": "^2.2.5", 31 | "core-js": "^2.4.1", 32 | "fullpage.js": "^2.9.5", 33 | "jquery": "^3.3.1", 34 | "meepo-axios": "^1.3.8", 35 | "meepo-common": "^1.1.5", 36 | "meepo-debuger": "^1.1.6", 37 | "meepo-utils": "^1.0.0-alpha.0", 38 | "meepo-we7-router": "^1.3.0", 39 | "ng-antd-mobile": "^1.0.5", 40 | "ng-antd-mobile-notice-bar": "^1.0.0-alpha.0", 41 | "normalize.css": "^7.0.0", 42 | "rxjs": "^5.5.2", 43 | "socket.io": "^2.0.4", 44 | "weui": "^1.1.2", 45 | "zone.js": "^0.8.14" 46 | }, 47 | "devDependencies": { 48 | "@angular/cli": "1.6.3", 49 | "@angular/compiler-cli": "^5.0.0", 50 | "@angular/language-service": "^5.0.0", 51 | "@types/jasmine": "~2.5.53", 52 | "@types/jasminewd2": "~2.0.2", 53 | "@types/node": "~6.0.60", 54 | "codelyzer": "^4.0.1", 55 | "jasmine-core": "~2.6.2", 56 | "jasmine-spec-reporter": "~4.1.0", 57 | "karma": "~1.7.0", 58 | "karma-chrome-launcher": "~2.1.1", 59 | "karma-cli": "~1.0.1", 60 | "karma-coverage-istanbul-reporter": "^1.2.1", 61 | "karma-jasmine": "~1.1.0", 62 | "karma-jasmine-html-reporter": "^0.2.2", 63 | "protractor": "~5.1.2", 64 | "ts-node": "~3.2.0", 65 | "tslint": "~5.7.0", 66 | "typescript": "~2.4.2" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /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/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | import 'core-js/es6/symbol'; 23 | import 'core-js/es6/object'; 24 | import 'core-js/es6/function'; 25 | import 'core-js/es6/parse-int'; 26 | import 'core-js/es6/parse-float'; 27 | import 'core-js/es6/number'; 28 | import 'core-js/es6/math'; 29 | import 'core-js/es6/string'; 30 | import 'core-js/es6/date'; 31 | import 'core-js/es6/array'; 32 | import 'core-js/es6/regexp'; 33 | import 'core-js/es6/map'; 34 | import 'core-js/es6/weak-map'; 35 | import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 38 | import 'classlist.js'; // Run `npm install --save classlist.js`. 39 | 40 | /** IE10 and IE11 requires the following for the Reflect API. */ 41 | import 'core-js/es6/reflect'; 42 | 43 | 44 | /** Evergreen browsers require these. **/ 45 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. 46 | import 'core-js/es7/reflect'; 47 | 48 | 49 | /** 50 | * Required to support Web Animations `@angular/platform-browser/animations`. 51 | * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation 52 | **/ 53 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 54 | 55 | 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js/dist/zone'; // Included with Angular CLI. 61 | 62 | 63 | 64 | /*************************************************************************************************** 65 | * APPLICATION IMPORTS 66 | */ 67 | -------------------------------------------------------------------------------- /src/app/danmus/danmu-item.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, OnInit, ElementRef, 3 | Renderer2, AfterViewInit, OnDestroy, Input 4 | } from '@angular/core'; 5 | import { HostBinding } from '@angular/core'; 6 | import { ViewEncapsulation } from '@angular/core'; 7 | import { EventEmitter, Output } from '@angular/core'; 8 | 9 | @Component({ 10 | selector: 'danmu-item', 11 | templateUrl: './danmu-item.html', 12 | styleUrls: ['./danmu-item.scss'], 13 | encapsulation: ViewEncapsulation.None 14 | }) 15 | export class DanmuItemComponent implements OnInit, AfterViewInit, OnDestroy { 16 | @HostBinding('class.danmu-item') _item: boolean = true; 17 | @HostBinding('style.top.px') _top: number = 0; 18 | // @HostBinding('style.left.px') _left: number = 0; 19 | @HostBinding('style.right.px') _right: number = 0; 20 | 21 | @HostBinding('style.min-width.em') _minWidth: number = 0; 22 | @HostBinding('style.max-width.em') _maxWidth: number = 0; 23 | 24 | @Input() avatar: string; 25 | @Input() item: any; 26 | 27 | @Output() onNext: EventEmitter = new EventEmitter(); 28 | @Output() onCenter: EventEmitter = new EventEmitter(); 29 | 30 | hasCenter: boolean = false; 31 | 32 | @Input() 33 | set len(len: number) { 34 | this._minWidth = len + 4; 35 | this._maxWidth = this._minWidth; 36 | } 37 | width: number; 38 | height: number; 39 | 40 | timeLen: number; 41 | fps: number = 60; 42 | timer: any; 43 | 44 | @Input() isnew: boolean = false; 45 | 46 | constructor( 47 | public ele: ElementRef, 48 | public render: Renderer2 49 | ) { } 50 | 51 | ngOnInit() { 52 | this.timeLen = 1 / this.fps! * 1000; 53 | this.randomPosition(); 54 | } 55 | 56 | ngOnDestroy() { 57 | clearInterval(this.timer); 58 | } 59 | 60 | randomPosition() { 61 | this.width = document.documentElement.clientWidth; 62 | this.height = document.documentElement.clientHeight; 63 | this._top = Math.random() * (this.height - 200) + 50; 64 | if (this.isnew) { 65 | this._right = - Math.random() * this.width + 200; 66 | } else { 67 | this._right = - Math.random() * this.width * 2; 68 | } 69 | } 70 | 71 | ngAfterViewInit() { 72 | const width = this.ele.nativeElement.clientWidth; 73 | this.timer = setInterval(() => { 74 | this._right++; 75 | if (this._right > this.width / 2) { 76 | if (!this.hasCenter) { 77 | this.onCenter.emit(this.item); 78 | this.hasCenter = true; 79 | } 80 | } 81 | if (this._right > this.width) { 82 | // this.randomPosition(); 83 | clearInterval(this.timer); 84 | this.onNext.emit(this.item); 85 | } 86 | }, this.timeLen); 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | [mnFullpage] { 2 | .section { 3 | line-height: 0; 4 | background-size: auto 100%; 5 | background-repeat: no-repeat; 6 | background-position: center; 7 | } 8 | } 9 | 10 | danmu-item { 11 | position: fixed; 12 | } 13 | 14 | .notice-bar { 15 | position: fixed; 16 | left: 0px; 17 | right: 0px; 18 | z-index: 9; 19 | top: 0px; 20 | } 21 | 22 | .footer { 23 | position: fixed; 24 | bottom: 0px; 25 | left: 0px; 26 | right: 0px; 27 | height: 50px; 28 | z-index: 9; 29 | .footer-wrap { 30 | display: flex; 31 | flex-direction: row; 32 | justify-content: center; 33 | align-items: center; 34 | width: 100%; 35 | height: 50px; 36 | .footer-input { 37 | flex: 1; 38 | input { 39 | max-width: 100%; 40 | min-width: 100%; 41 | height: 50px; 42 | background-color: #efefef; 43 | border: none; 44 | outline: none; 45 | padding-left: 10px; 46 | font-size: 1.1em; 47 | border-radius: 0px; 48 | } 49 | } 50 | .footer-send, 51 | .footer-cancel { 52 | width: 4em; 53 | display: flex; 54 | align-items: center; 55 | justify-content: center; 56 | flex-direction: row; 57 | height: 50px; 58 | background: #c70707; 59 | color: #fff; 60 | } 61 | } 62 | } 63 | 64 | video { 65 | display: block; 66 | position: fixed; 67 | z-index: 99; 68 | left: 0px; 69 | right: 0px; 70 | top: 0px; 71 | right: 0px; 72 | background: #fff; 73 | } 74 | 75 | .main-info { 76 | position: fixed; 77 | bottom: 60px; 78 | left: 10px; 79 | padding: 10px; 80 | background: rgba(0, 0, 0, .5); 81 | color: #fff; 82 | font-size: .8em; 83 | border-radius: 10px; 84 | a { 85 | color: #fff; 86 | &:active, 87 | &:link { 88 | color: #fff; 89 | } 90 | } 91 | } 92 | 93 | .avatar-list { 94 | height: 30px; 95 | display: flex; 96 | flex-direction: row; 97 | align-items: center; 98 | padding-left: 0px; 99 | overflow: auto; 100 | margin: 0xp; 101 | padding: 0px; 102 | border: none; 103 | .info { 104 | color: #fff; 105 | background: red; 106 | padding-right: 0px; 107 | min-width: 64px; 108 | width: 64px; 109 | font-size: 14px; 110 | height: 45px; 111 | line-height: 45px; 112 | } 113 | img { 114 | width: 30px; 115 | height: 30px; 116 | min-width: 30px; 117 | max-width: 30px; 118 | border-radius: 50%; 119 | margin-left: -10px; 120 | -webkit-overflow-scrolling: touch; 121 | &:hover { 122 | transform: scale(1.3); 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /src/app/shared/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, isDevMode } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | import { We7RouterService } from 'meepo-we7-router'; 4 | import { Location } from '@angular/common'; 5 | import { FormBuilder, FormGroup } from '@angular/forms'; 6 | 7 | @Injectable() 8 | export class AppService { 9 | props: any; 10 | version: string = '1.0.4'; 11 | form: FormGroup; 12 | userinfo: any; 13 | constructor( 14 | public http: HttpClient, 15 | public router: We7RouterService, 16 | public location: Location, 17 | public fb: FormBuilder 18 | ) { 19 | let url = '../addons/shibida_mfans/template/mobile/assets/app.json?t=' + new Date().getTime(); 20 | if (isDevMode()) { 21 | url = './assets/app.json?t=' + new Date().getTime(); 22 | } 23 | this.http.get(url).subscribe(res => { 24 | this.props = res; 25 | }); 26 | this.form = this.fb.group({ 27 | car: [], 28 | check: [], 29 | goods: [], 30 | needXiche: 0, 31 | services: [], 32 | employers: [], 33 | message: [''], 34 | tid: [this.guid()] 35 | }); 36 | let values = localStorage.getItem('shibida:form'); 37 | if (values) { 38 | let items = JSON.parse(values); 39 | for (let key in items) { 40 | this.form.get(key).setValue(items[key]); 41 | } 42 | } 43 | this.form.valueChanges.subscribe(res => { 44 | console.log(res); 45 | localStorage.setItem('shibida:form', JSON.stringify(res)); 46 | }); 47 | } 48 | 49 | guid() { 50 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 51 | var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); 52 | return v.toString(16); 53 | }); 54 | } 55 | 56 | initForm() { 57 | 58 | } 59 | 60 | refreshForm() { 61 | 62 | } 63 | 64 | back() { 65 | this.location.back(); 66 | } 67 | 68 | autoLogin() { 69 | let url = this.getMobileUrl('checklogin'); 70 | this.http.get(url).subscribe((res: any) => { 71 | this.userinfo = res.info; 72 | }); 73 | } 74 | 75 | getUrl(_do: string, params?: any) { 76 | let url = ''; 77 | if (isDevMode()) { 78 | url = `./assets/${_do}.json?t=` + new Date().getTime(); 79 | } else { 80 | url = this.router.puts({ 81 | do: _do, 82 | ...params 83 | }); 84 | } 85 | return url; 86 | } 87 | 88 | getMobileUrl(_do: string, params?: any) { 89 | let url = this.getUrl(_do, params); 90 | if (isDevMode()) { 91 | return url; 92 | } 93 | return `${location.protocol}//${location.host}/app/index.php${url}` 94 | } 95 | 96 | getWebUrl(_do: string, params?: any) { 97 | let url = this.getUrl(_do, params); 98 | if (isDevMode()) { 99 | return url; 100 | } 101 | return `${location.protocol}//${location.host}/web/index.php${url}` 102 | } 103 | 104 | toRegister() { 105 | this.router.go('register', {}); 106 | } 107 | 108 | toForget() { 109 | this.router.go('forget', {}); 110 | } 111 | 112 | toLogin() { 113 | this.router.go('login', {}); 114 | } 115 | 116 | loginSuccess(item: any) { 117 | const _do = localStorage.getItem('login.success'); 118 | sessionStorage.setItem('uid', item.id); 119 | if (_do) { 120 | this.router.go(_do, { uid: item.id }); 121 | } else { 122 | this.router.go('index', { uid: item.id }); 123 | } 124 | } 125 | 126 | tip(msg: string) { 127 | alert(msg); 128 | } 129 | } -------------------------------------------------------------------------------- /src/app/lazyload/lazyload-image.directive.ts: -------------------------------------------------------------------------------- 1 | import 'rxjs/add/operator/let'; 2 | import 'rxjs/add/operator/switchMap'; 3 | import 'rxjs/add/operator/debounceTime'; 4 | import { Observable } from 'rxjs/Observable'; 5 | import { ReplaySubject } from 'rxjs/ReplaySubject'; 6 | import { 7 | AfterContentInit, 8 | Directive, 9 | ElementRef, 10 | EventEmitter, 11 | Input, 12 | NgZone, 13 | Output, 14 | OnChanges, 15 | OnDestroy, 16 | SimpleChanges 17 | } from '@angular/core'; 18 | import { getScrollListener } from './scroll-listener'; 19 | import { lazyLoadImage } from './lazyload-image'; 20 | import { isWindowDefined } from './utils'; 21 | 22 | interface LazyLoadImageDirectiveProps { 23 | lazyImage: string; 24 | defaultImage: string; 25 | errorImage: string; 26 | scrollTarget: any; 27 | scrollObservable: Observable; 28 | offset: number; 29 | useSrcset: boolean; 30 | } 31 | 32 | @Directive({ 33 | selector: '[lazyLoad]' 34 | }) 35 | export class LazyLoadImageDirective implements OnChanges, AfterContentInit, OnDestroy { 36 | @Input('lazyLoad') lazyImage; // The image to be lazy loaded 37 | @Input() defaultImage: string; // The image to be displayed before lazyImage is loaded 38 | @Input() errorImage: string; // The image to be displayed if lazyImage load fails 39 | @Input() scrollTarget: any; // Scroll container that contains the image and emits scoll events 40 | @Input() scrollObservable; // Pass your own scroll emitter 41 | @Input() offset: number; // The number of px a image should be loaded before it is in view port 42 | @Input() useSrcset: boolean; // Whether srcset attribute should be used instead of src 43 | @Output() onLoad: EventEmitter = new EventEmitter(); // Callback when an image is loaded 44 | private propertyChanges$: ReplaySubject; 45 | private elementRef: ElementRef; 46 | private ngZone: NgZone; 47 | private scrollSubscription; 48 | 49 | constructor(el: ElementRef, ngZone: NgZone) { 50 | this.elementRef = el; 51 | this.ngZone = ngZone; 52 | this.propertyChanges$ = new ReplaySubject(); 53 | } 54 | 55 | ngOnChanges(changes?: SimpleChanges) { 56 | this.propertyChanges$.next({ 57 | lazyImage: this.lazyImage, 58 | defaultImage: this.defaultImage, 59 | errorImage: this.errorImage, 60 | scrollTarget: this.scrollTarget, 61 | scrollObservable: this.scrollObservable, 62 | offset: this.offset | 0, 63 | useSrcset: this.useSrcset 64 | }); 65 | } 66 | 67 | ngAfterContentInit() { 68 | // Disable lazy load image in server side 69 | if (!isWindowDefined()) { 70 | return null; 71 | } 72 | 73 | this.ngZone.runOutsideAngular(() => { 74 | let scrollObservable: Observable; 75 | if (this.scrollObservable) { 76 | scrollObservable = this.scrollObservable.startWith(''); 77 | } else { 78 | const windowTarget = isWindowDefined() ? window : undefined; 79 | scrollObservable = getScrollListener(this.scrollTarget || windowTarget); 80 | } 81 | this.scrollSubscription = this.propertyChanges$ 82 | .debounceTime(10) 83 | .switchMap(props => scrollObservable.let( 84 | lazyLoadImage( 85 | this.elementRef.nativeElement, 86 | props.lazyImage, 87 | props.defaultImage, 88 | props.errorImage, 89 | props.offset, 90 | props.useSrcset, 91 | props.scrollTarget 92 | ) 93 | )) 94 | .subscribe(success => this.onLoad.emit(success)); 95 | }); 96 | } 97 | 98 | ngOnDestroy() { 99 | [this.scrollSubscription] 100 | .filter(subscription => subscription && !subscription.isUnsubscribed) 101 | .forEach(subscription => subscription.unsubscribe()); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/app/lazyload/lazyload-image.ts: -------------------------------------------------------------------------------- 1 | import 'rxjs/add/operator/filter'; 2 | import 'rxjs/add/operator/do'; 3 | import 'rxjs/add/operator/take'; 4 | import 'rxjs/add/operator/map'; 5 | import 'rxjs/add/operator/mergeMap'; 6 | import 'rxjs/add/operator/catch'; 7 | import 'rxjs/add/observable/of'; 8 | import { Observable } from 'rxjs/Observable'; 9 | import { getScrollListener } from './scroll-listener'; 10 | import { Rect } from './rect'; 11 | import { cssClassNames } from './constants'; 12 | 13 | export function isVisible(element: HTMLElement, threshold = 0, _window: Window, scrollContainer?: HTMLElement) { 14 | const elementBounds = Rect.fromElement(element); 15 | const windowBounds = Rect.fromWindow(_window); 16 | elementBounds.inflate(threshold); 17 | 18 | if (scrollContainer) { 19 | const scrollContainerBounds = Rect.fromElement(scrollContainer); 20 | const intersection = scrollContainerBounds.getIntersectionWith(windowBounds); 21 | return elementBounds.intersectsWith(intersection); 22 | } else { 23 | return elementBounds.intersectsWith(windowBounds); 24 | } 25 | } 26 | 27 | export function isChildOfPicture(element: HTMLImageElement | HTMLDivElement): boolean { 28 | return Boolean(element.parentElement && element.parentElement.nodeName.toLowerCase() === 'picture'); 29 | } 30 | 31 | export function isImageElement(element: HTMLImageElement | HTMLDivElement): element is HTMLImageElement { 32 | return element.nodeName.toLowerCase() === 'img'; 33 | } 34 | 35 | function loadImage(element: HTMLImageElement | HTMLDivElement, imagePath: string, useSrcset: boolean): Observable { 36 | let img: HTMLImageElement; 37 | if (isImageElement(element) && isChildOfPicture(element)) { 38 | const parentClone = element.parentNode.cloneNode(true) as HTMLPictureElement; 39 | img = parentClone.getElementsByTagName('img')[0]; 40 | setSourcesToLazy(img); 41 | setImage(img, imagePath, useSrcset); 42 | } else { 43 | img = new Image(); 44 | if (isImageElement(element) && element.sizes) { 45 | img.sizes = element.sizes; 46 | } 47 | if (useSrcset) { 48 | img.srcset = imagePath; 49 | } else { 50 | img.src = imagePath; 51 | } 52 | } 53 | 54 | return Observable 55 | .create(observer => { 56 | img.onload = () => { 57 | observer.next(imagePath); 58 | observer.complete(); 59 | }; 60 | img.onerror = err => { 61 | observer.error(null); 62 | }; 63 | }); 64 | } 65 | 66 | function setImage(element: HTMLImageElement | HTMLDivElement, imagePath: string, useSrcset: boolean) { 67 | if (isImageElement(element)) { 68 | if (useSrcset) { 69 | element.srcset = imagePath; 70 | } else { 71 | element.src = imagePath; 72 | } 73 | } else { 74 | element.style.backgroundImage = `url('${imagePath}')`; 75 | } 76 | return element; 77 | } 78 | 79 | function setSources(attrName: string) { 80 | return (image: HTMLImageElement) => { 81 | const sources = image.parentElement.getElementsByTagName('source'); 82 | for (let i = 0; i < sources.length; i++) { 83 | const attrValue = sources[i].getAttribute(attrName); 84 | if (attrValue) { 85 | sources[i].srcset = attrValue; 86 | } 87 | } 88 | }; 89 | } 90 | 91 | const setSourcesToDefault = setSources('defaultImage'); 92 | const setSourcesToLazy = setSources('lazyLoad'); 93 | const setSourcesToError = setSources('errorImage'); 94 | 95 | function setImageAndSources(setSourcesFn: (image: HTMLImageElement) => void) { 96 | return (element: HTMLImageElement | HTMLDivElement, imagePath: string, useSrcset: boolean) => { 97 | if (isImageElement(element) && isChildOfPicture(element)) { 98 | setSourcesFn(element); 99 | } 100 | if (imagePath) { 101 | setImage(element, imagePath, useSrcset); 102 | } 103 | }; 104 | } 105 | 106 | const setImageAndSourcesToDefault = setImageAndSources(setSourcesToDefault); 107 | const setImageAndSourcesToLazy = setImageAndSources(setSourcesToLazy); 108 | const setImageAndSourcesToError = setImageAndSources(setSourcesToError); 109 | 110 | function setLoadedStyle(element: HTMLImageElement | HTMLDivElement) { 111 | const styles = element.className 112 | .split(' ') 113 | .filter(s => !!s) 114 | .filter(s => s !== cssClassNames.loading); 115 | styles.push(cssClassNames.loaded); 116 | element.className = styles.join(' '); 117 | return element; 118 | } 119 | 120 | export function lazyLoadImage(element: HTMLImageElement | HTMLDivElement, imagePath: string, defaultImagePath: string, errorImgPath: string, offset: number, useSrcset: boolean = false, scrollContainer?: HTMLElement) { 121 | setImageAndSourcesToDefault(element, defaultImagePath, useSrcset); 122 | if (element.className && element.className.includes(cssClassNames.loaded)) { 123 | element.className = element.className.replace(cssClassNames.loaded, ''); 124 | } 125 | 126 | return (scrollObservable: Observable) => { 127 | return scrollObservable 128 | .filter(() => isVisible(element, offset, window, scrollContainer)) 129 | .take(1) 130 | .mergeMap(() => loadImage(element, imagePath, useSrcset)) 131 | .do(() => setImageAndSourcesToLazy(element, imagePath, useSrcset)) 132 | .map(() => true) 133 | .catch(() => { 134 | setImageAndSourcesToError(element, errorImgPath, useSrcset); 135 | element.className += ' ' + cssClassNames.failed; 136 | return Observable.of(false); 137 | }) 138 | .do(() => setLoadedStyle(element)); 139 | }; 140 | } 141 | -------------------------------------------------------------------------------- /src/app/fullpage/mnFullpage.service.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Meiblorn (Vadim Fedorenko) on 11/05/16. 3 | */ 4 | 5 | import { Injectable } from '@angular/core'; 6 | @Injectable() 7 | export class MnFullpageService { 8 | 9 | //noinspection JSMethodCanBeStatic 10 | /** 11 | * Scrolls one section up 12 | */ 13 | public moveSectionUp(): void { 14 | $.fn.fullpage.moveSectionUp(); 15 | } 16 | 17 | //noinspection JSMethodCanBeStatic 18 | /** 19 | * Scrolls one section down 20 | */ 21 | public moveSectionDown() { 22 | $.fn.fullpage.moveSectionDown(); 23 | } 24 | 25 | //noinspection JSMethodCanBeStatic 26 | /** 27 | * Scrolls the page to the given section and slide. 28 | * The first slide, the visible one by default, will have index 0. 29 | * 30 | * @param section 31 | * @param slide 32 | */ 33 | public moveTo(section: string | number, slide?: number) { 34 | $.fn.fullpage.moveTo(section, slide); 35 | } 36 | 37 | //noinspection JSMethodCanBeStatic 38 | /** 39 | * Exactly the same as moveTo but in this case it performs the scroll without animation. 40 | * A direct jump to the destination. 41 | * 42 | * @param section 43 | * @param slide 44 | */ 45 | public silentMoveTo(section: string | number, slide?: number) { 46 | $.fn.fullpage.silentMoveTo(section, slide); 47 | } 48 | 49 | //noinspection JSMethodCanBeStatic 50 | /** 51 | * Scrolls the horizontal slider of the current section to the next slide 52 | */ 53 | public moveSlideRight() { 54 | $.fn.fullpage.moveSlideRight(); 55 | } 56 | 57 | //noinspection JSMethodCanBeStatic 58 | /** 59 | * Scrolls the horizontal slider of the current section to the previous slide 60 | */ 61 | public moveSlideLeft() { 62 | $.fn.fullpage.moveSlideLeft(); 63 | } 64 | 65 | //noinspection JSMethodCanBeStatic 66 | /** 67 | * Sets the scrolling configuration in real time. 68 | * Defines the way the page scrolling behaves. If it is set to true, 69 | * it will use the "automatic" scrolling, otherwise, it will use the "manual" 70 | * or "normal" scrolling of the site. Be careful when combining this option with 71 | * scrollOverflow set to true, as it might be difficult to scroll using the mouse 72 | * wheel or the trackpad when the section is scrollable 73 | * 74 | * @param enable 75 | */ 76 | public setAutoScrolling(enable: boolean) { 77 | $.fn.fullpage.setAutoScrolling(enable); 78 | } 79 | 80 | //noinspection JSMethodCanBeStatic 81 | /** 82 | * Sets the value for the option fitToSection determining whether to fit 83 | * the section in the screen or not. 84 | * 85 | * @param enable 86 | */ 87 | public setFitToSection(enable: boolean) { 88 | $.fn.fullpage.setFitToSection(enable); 89 | } 90 | 91 | //noinspection JSMethodCanBeStatic 92 | /** 93 | * Sets the value for the option lockAnchors determining whether 94 | * anchors will have any effect in the URL or not. 95 | * 96 | * @param enable 97 | */ 98 | public setLockAnchors(enable: boolean) { 99 | $.fn.fullpage.setLockAnchors(enable); 100 | } 101 | 102 | //noinspection JSMethodCanBeStatic 103 | /** 104 | * Adds or remove the possibility of scrolling through sections by 105 | * using the mouse wheel/trackpad or touch gestures (which is active 106 | * by default). Note this won't disable the keyboard scrolling. 107 | * You would need to use setKeyboardScrolling for it. 108 | * 109 | * Directions: (optional parameter) Admitted values: all, up, down, 110 | * left, right or a combination of them separated by commas like down, 111 | * right. It defines the direction for which the scrolling will 112 | * be enabled or disabled. 113 | * 114 | * @param allow 115 | * @param directions 116 | */ 117 | public setAllowScrolling(allow: boolean, directions?: string) { 118 | $.fn.fullpage.setAllowScrolling(allow, directions); 119 | } 120 | 121 | //noinspection JSMethodCanBeStatic 122 | /** 123 | * Adds or remove the possibility of scrolling through sections by 124 | * using the keyboard arrow keys (which is active by default). 125 | * 126 | * Directions: (optional parameter) Admitted values: all, up, down, 127 | * left, right or a combination of them separated by commas like down, 128 | * right. It defines the direction for which the scrolling will be 129 | * enabled or disabled. 130 | * 131 | * @param allow 132 | * @param directions 133 | */ 134 | public setKeyboardScrolling(allow: boolean, directions?: string) { 135 | $.fn.fullpage.setKeyboardScrolling(allow, directions); 136 | } 137 | 138 | //noinspection JSMethodCanBeStatic 139 | /** 140 | * Defines whether to record the history for each hash change in the URL 141 | * 142 | * @param enable 143 | */ 144 | public setRecordHistory(enable: boolean) { 145 | $.fn.fullpage.setRecordHistory(enable); 146 | } 147 | 148 | //noinspection JSMethodCanBeStatic 149 | /** 150 | * Defines the scrolling speed in milliseconds 151 | * 152 | * @param milliseconds 153 | */ 154 | public setScrollingSpeed(milliseconds: number) { 155 | $.fn.fullpage.setScrollingSpeed(milliseconds); 156 | } 157 | 158 | //noinspection JSMethodCanBeStatic 159 | /** 160 | * Destroys the plugin events and optionally its HTML markup and styles. 161 | * Ideal to use when using AJAX to load content. 162 | * 163 | * type: can be empty or all. If all is passed, the HTML markup and styles 164 | * used by fullpage.js will be removed. This way the original HTML markup, 165 | * the one used before any plugin modification is made, will be maintained. 166 | * 167 | * @param type 168 | */ 169 | public destroy(type: string) { 170 | $.fn.fullpage.destroy(type); 171 | } 172 | 173 | //noinspection JSMethodCanBeStatic 174 | /** 175 | * Updates the DOM structure to fit the new window size or its contents. 176 | * Ideal to use in combination with AJAX calls or external changes in the 177 | * DOM structure of the site. 178 | */ 179 | public reBuild() { 180 | $.fn.fullpage.reBuild(); 181 | } 182 | 183 | } 184 | -------------------------------------------------------------------------------- /service/README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | [travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master 6 | [travis-url]: https://travis-ci.org/nestjs/nest 7 | [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux 8 | [linux-url]: https://travis-ci.org/nestjs/nest 9 | 10 |

A progressive Node.js framework for building efficient and scalable server-side applications.

11 |

12 | NPM Version 13 | Package License 14 | NPM Downloads 15 | Travis 16 | Linux 17 | Coverage 18 | Gitter 19 | Backers on Open Collective 20 | Sponsors on Open Collective 21 |

22 | 24 | 25 | ## Description 26 | 27 | [Nest](https://github.com/nestjs/nest) framework **TypeScript** starter repository. 28 | 29 | ## Installation 30 | 31 | ```bash 32 | $ npm install 33 | ``` 34 | 35 | ## Start 36 | 37 | ``` 38 | $ npm run start 39 | ``` 40 | 41 | ## People 42 | 43 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) 44 | - Website - [https://nestjs.com](https://nestjs.com/) 45 | 46 | ## Backers 47 | 48 | I am on a mission to provide an architecture to create truly flexible, scalable and loosely coupled systems using the Node.js platform. It takes a lot of time, so if you want to support me, please [become a backer / sponsor]((https://opencollective.com/nest#backer)). I appreciate your help. Thanks! :heart_eyes: 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, ViewContainerRef, 3 | OnInit, AfterViewInit, ViewChild, 4 | Renderer2, isDevMode 5 | } from '@angular/core'; 6 | import { MnFullpageOptions } from './fullpage'; 7 | import { Subject } from 'rxjs/Subject'; 8 | import { DanmuItemComponent } from './danmus/danmu-item'; 9 | import { HttpClient } from '@angular/common/http'; 10 | import { ElementRef } from '@angular/core'; 11 | import * as io from 'socket.io-client'; 12 | import { fromEvent } from 'rxjs/observable/fromEvent'; 13 | export const randomContents = [ 14 | '为我们送上祝福吧', 15 | '新郎帅不帅', 16 | '新娘美不美', 17 | '来,在这输入,我带你飞', 18 | '听说你知道新郎的秘密', 19 | '听说你知道新娘的秘密', 20 | '来不及解释了,快上车', 21 | '颜值高的和祝福多的都有机会中奖', 22 | '据说2月7号弹幕会下红包雨', 23 | '你怎么才来啊', 24 | '终于等到你,还好我没放弃', 25 | '让祝福飞一会儿', 26 | '你知道新郎和新娘是怎么认识的吗', 27 | '执子之手,与子一起抢红包', 28 | '天将降红包于斯人也', 29 | '百年好合,红包大额', 30 | '新婚大喜喜洋洋,合家欢乐乐洋洋', 31 | '今天的风洋溢着喜悦与欢乐,今天的天弥漫著幸福与甜蜜', 32 | '天搭鹊桥,人间巧奇,一对鸳鸯,恰逢新禧,花开成双', 33 | '喜接连理,甜甜蜜蜜,百年夫妻', 34 | '天喜,地喜,人也喜,物喜,事喜,样样喜', 35 | '让这缠绵的诗句,敲响幸福的钟声。', 36 | '愿你俩永浴爱河,白头偕老!', 37 | '愿你俩恩恩爱爱,意笃情深', 38 | '此生爱情永恒,爱心与日俱增!', 39 | '祝你们永结同心,百年好合!新婚愉快,甜甜蜜蜜!', 40 | '千里姻缘情牵引,高山万水难断爱。今朝已定百年好', 41 | '愿祝新人共白首!', 42 | '白首齐眉鸳鸯比翼,青阳启瑞桃李同心。', 43 | '房花烛交颈鸳鸯双得意,夫妻恩爱和鸣凤鸾两多情' 44 | ]; 45 | 46 | const audios = [ 47 | 'audio.mp3', 48 | 'audio3.mp3', 49 | 'audio4.mp3', 50 | 'audio5.mp3', 51 | 'audio6.mp3', 52 | 'audio7.mp3', 53 | 'audio8.mp3', 54 | 'audio9.mp3' 55 | ]; 56 | 57 | export interface FuyueForms { 58 | realname?: string; 59 | mobile?: string; 60 | openid?: string; 61 | avatar?: string; 62 | content?: string; 63 | nickname?: string; 64 | create_time?: number; 65 | } 66 | @Component({ 67 | selector: 'app-root', 68 | templateUrl: './app.component.html', 69 | styleUrls: ['./app.component.scss'] 70 | }) 71 | export class AppComponent implements OnInit, AfterViewInit { 72 | title = 'app'; 73 | 74 | cfg: any = { 75 | mnFullpageAfterLoad: (...args) => { 76 | this.nowIndex$.next(args[1]); 77 | } 78 | }; 79 | _audioRandom: string; 80 | 81 | nowIndex$: Subject; 82 | showAdv: boolean = true; 83 | components: any[] = []; 84 | allComponents: any[] = []; 85 | 86 | @ViewChild('audio') audio: ElementRef; 87 | @ViewChild('video') video: ElementRef; 88 | @ViewChild('send') send: ElementRef; 89 | @ViewChild('footer') footer: ElementRef; 90 | 91 | 92 | hasFuyue: boolean = false; 93 | 94 | height: number = 0; 95 | width: number = 0; 96 | socket: SocketIOClient.Socket; 97 | 98 | showFuyue: boolean = false; 99 | 100 | fuyues: any[] = []; 101 | fuyueForm: FuyueForms = {}; 102 | begin: number = 10; 103 | 104 | constructor( 105 | private _view: ViewContainerRef, 106 | public http: HttpClient, 107 | public render: Renderer2 108 | ) { 109 | this.nowIndex$ = new Subject(); 110 | this.hasFuyue = localStorage.getItem('hasFuyue') ? true : false; 111 | } 112 | setAudioRandom() { 113 | this._audioRandom = `../addons/meepo_hunli/template/mobile/assets/${audios[Math.floor(Math.random() * audios.length)]}`; 114 | if (this.audio) { 115 | const audio = this.audio.nativeElement as HTMLAudioElement; 116 | if (audio) { 117 | audio.src = this._audioRandom; 118 | audio.onload = () => { 119 | audio.play(); 120 | }; 121 | } 122 | } 123 | } 124 | 125 | ngOnInit() { 126 | this.setAudioRandom(); 127 | this.width = document.documentElement.clientWidth; 128 | this.height = document.documentElement.clientHeight; 129 | setTimeout(() => { 130 | this.showAdv = false; 131 | }, 3000); 132 | document.addEventListener('WeixinJSBridgeReady', () => { 133 | this.audio.nativeElement.play(); 134 | }, false); 135 | document.addEventListener('YixinJSBridgeReady', () => { 136 | this.audio.nativeElement.play(); 137 | }, false); 138 | if (isDevMode()) { 139 | this.socket = io('http://localhost:1314'); 140 | } else { 141 | this.socket = io('https://meepo.com.cn'); 142 | } 143 | this.socket.emit('hunli.discuss', ''); 144 | this.socket.on('hunli.discuss', (list) => { 145 | const lists = []; 146 | // 所有的评论 147 | list.map((li: any) => { 148 | lists.push({ 149 | avatar: li.avatar, 150 | content: li.content 151 | }); 152 | }); 153 | this.allComponents = list; 154 | this.createRandomComponents(); 155 | }); 156 | 157 | this.socket.on('hunli.discuss.add', (item) => { 158 | item['isnew'] = true; 159 | this.components.push(item); 160 | }); 161 | 162 | this.socket.on('hunli.fuyue.add', (item) => { 163 | item['isnew'] = true; 164 | this.fuyues.unshift(item); 165 | }); 166 | this.socket.emit('hunli.fuyue', ''); 167 | this.socket.on('hunli.fuyue', (item) => { 168 | this.fuyues = item || []; 169 | }); 170 | this.initWx(); 171 | 172 | fromEvent(this.send.nativeElement, 'focus').subscribe(res => { 173 | this.render.setStyle(this.footer.nativeElement, 'position', 'absolute'); 174 | }); 175 | fromEvent(this.send.nativeElement, 'bulr').subscribe(res => { 176 | this.render.setStyle(this.footer.nativeElement, 'position', 'fixed'); 177 | }); 178 | } 179 | 180 | initWx() { 181 | wx.ready(() => { 182 | const data = { 183 | title: '杨明明&闫聪玲-我们要结婚啦', 184 | desc: '时间:农历22,阳历2月7号,地址: 安阳市滑县万古镇棘马林村', 185 | link: sysinfo.siteurl, 186 | imgUrl: 'https://meepo.com.cn/addons/meepo_hunli/template/mobile/assets/images/8.lazy.png', 187 | success: () => { 188 | console.log('share success'); 189 | }, 190 | cancel: () => { 191 | console.log('share cancel'); 192 | } 193 | }; 194 | wx.onMenuShareTimeline(data); 195 | wx.onMenuShareAppMessage(data); 196 | wx.onMenuShareQQ(data); 197 | wx.onMenuShareWeibo(data); 198 | wx.onMenuShareQZone(data); 199 | }); 200 | } 201 | // 创建初始随机评论 202 | private createRandomComponents() { 203 | localStorage.setItem('allComponents', JSON.stringify(this.allComponents)); 204 | this.allComponents.map((res, index) => { 205 | if (index <= this.begin) { 206 | this.components.push(res); 207 | } 208 | }); 209 | } 210 | 211 | createNextComponents(index: any) { 212 | this.components.indexOf(index); 213 | this.components.splice(index, 1); 214 | } 215 | 216 | onCenter() { 217 | this.begin++; 218 | if (this.begin < this.allComponents.length) { 219 | this.components.push(this.allComponents[this.begin]); 220 | } else { 221 | this.begin = 0; 222 | this.components.push(this.allComponents[this.begin]); 223 | } 224 | } 225 | 226 | ngAfterViewInit() { 227 | this.audio.nativeElement.play(); 228 | } 229 | 230 | switchPlay() { 231 | this.setAudioRandom(); 232 | this.audio.nativeElement.play(); 233 | } 234 | 235 | doSend() { 236 | const content = this.send.nativeElement.value; 237 | if (content.length < 3) { 238 | alert('太吝啬了吧,3个字都不给我!'); 239 | return ''; 240 | } 241 | const data = { 242 | content: content, 243 | openid: UserInfo.openid, 244 | avatar: UserInfo.avatar, 245 | create_time: Math.floor(new Date().getTime() / 1000) 246 | }; 247 | this.socket.emit('hunli.discuss.add', data); 248 | this.send.nativeElement.value = ''; 249 | } 250 | doFuyue() { 251 | this.showFuyue = true; 252 | } 253 | 254 | confirmFuyue() { 255 | this.fuyueForm.openid = UserInfo.openid; 256 | this.fuyueForm.avatar = UserInfo.avatar; 257 | this.fuyueForm.nickname = UserInfo.nickname; 258 | this.fuyueForm.create_time = Math.floor(new Date().getTime() / 1000); 259 | this.fuyueForm.content = this.send.nativeElement.value; 260 | this.socket.emit('hunli.fuyue.add', this.fuyueForm); 261 | // 初始化 262 | this.hasFuyue = true; 263 | this.showFuyue = false; 264 | localStorage.setItem('hasFuyue', 'true'); 265 | this.send.nativeElement.value = ''; 266 | } 267 | 268 | cancelFuyue(e: any) { 269 | this.showFuyue = false; 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /src/app/fullpage/mnFullpage.directive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Meiblorn (Vadim Fedorenko) on 12/05/16. 3 | */ 4 | 5 | import { Directive, ElementRef, Input, OnInit, AfterViewInit } from '@angular/core'; 6 | import { MnFullpageOptions } from './mnFullpage-options.class'; 7 | 8 | const DIRECTIVE_NAME = 'mnFullpage'; 9 | 10 | @Directive({ 11 | selector: '[' + DIRECTIVE_NAME + ']' 12 | }) 13 | export class MnFullpageDirective implements AfterViewInit { 14 | 15 | /** 16 | * Prefix for directive-relative properties 17 | * 18 | * @type {string} prefix 19 | */ 20 | private static propertyPrefix: string = DIRECTIVE_NAME; 21 | 22 | /** 23 | * Directive options reference 24 | */ 25 | /* tslint:disable */ 26 | @Input(DIRECTIVE_NAME) public options: MnFullpageOptions; 27 | /* tslint:enable */ 28 | 29 | /** 30 | * Index signature 31 | */ 32 | [key: string]: any; 33 | 34 | /** 35 | * --------------------------------------------------------------------------- 36 | * | Navigation | 37 | * --------------------------------------------------------------------------- 38 | * 39 | * @see MnFullpageOptions for documentation 40 | */ 41 | 42 | @Input() public mnFullpageMenu: string; 43 | @Input() public mnFullpageLockAnchors: boolean; 44 | @Input() public mnFullpageAnchors: Array; 45 | @Input() public mnFullpageNavigation: boolean; 46 | @Input() public mnFullpageNavigationPosition: string; 47 | @Input() public mnFullpageNavigationTooltips: Array; 48 | @Input() public mnFullpageShowActiveTooltip: boolean; 49 | @Input() public mnFullpageSlidesNavigation: boolean; 50 | @Input() public mnFullpageSlidesNavPosition: string; 51 | 52 | /** 53 | * --------------------------------------------------------------------------- 54 | * | Scrolling | 55 | * --------------------------------------------------------------------------- 56 | * 57 | * @see MnFullpageOptions for documentation 58 | */ 59 | 60 | @Input() public mnFullpageCss3: boolean; 61 | @Input() public mnFullpageScrollingSpeed: number; 62 | @Input() public mnFullpageAutoScrolling: boolean; 63 | @Input() public mnFullpageFitToSection: boolean; 64 | @Input() public mnFullpageFitToSectionDelay: number; 65 | @Input() public mnFullpageScrollBar: boolean; 66 | @Input() public mnFullpageEasing: string; 67 | @Input() public mnFullpageEasingcss3: string; 68 | @Input() public mnFullpageLoopBottom: boolean; 69 | @Input() public mnFullpageLoopTop: boolean; 70 | @Input() public mnFullpageLoopHorizontal: boolean; 71 | @Input() public mnFullpageContinuousVertical: boolean; 72 | @Input() public mnFullpageNormalScrollElements: string; 73 | @Input() public mnFullpageScrollOverflow: boolean; 74 | @Input() public mnFullpageTouchSensitivity: number; 75 | @Input() public mnFullpageNormalScrollElementTouchThreshold: number; 76 | 77 | /** 78 | * --------------------------------------------------------------------------- 79 | * | Accessibility | 80 | * --------------------------------------------------------------------------- 81 | * 82 | * @see MnFullpageOptions for documentation 83 | */ 84 | 85 | @Input() public mnFullpageKeyboardScrolling: boolean; 86 | @Input() public mnFullpageAnimateAnchor: boolean; 87 | @Input() public mnFullpageRecordHistory: boolean; 88 | 89 | /** 90 | * --------------------------------------------------------------------------- 91 | * | Design | 92 | * --------------------------------------------------------------------------- 93 | * 94 | * @see MnFullpageOptions for documentation 95 | */ 96 | 97 | @Input() public mnFullpageControlArrows: boolean; 98 | @Input() public mnFullpageVerticalCentered: boolean; 99 | @Input() public mnFullpageResize: boolean; 100 | @Input() public mnFullpageSectionsColor: Array; 101 | @Input() public mnFullpagePaddingTop: string; 102 | @Input() public mnFullpagePaddingBottom: string; 103 | @Input() public mnFullpageFixedElements: string; 104 | @Input() public mnFullpageResponsiveWidth: number; 105 | @Input() public mnFullpageResponsiveHeight: number; 106 | @Input() public mnFullpageSectionSelector: string; 107 | @Input() public mnFullpageSlideSelector: string; 108 | 109 | /** 110 | * --------------------------------------------------------------------------- 111 | * | Callbacks | 112 | * --------------------------------------------------------------------------- 113 | * 114 | * @see MnFullpageOptions for documentation 115 | */ 116 | 117 | @Input() public mnFullpageAfterLoad: (anchorLink: string, index: number) => void; 118 | @Input() public mnFullpageOnLeave: (index: number, nextIndex: number, 119 | direction: string) => void; 120 | @Input() public mnFullpageAfterRender: () => void; 121 | @Input() public mnFullpageAfterResize: () => void; 122 | @Input() public mnFullpageAfterSlideLoad: (anchorLink: string, index: number, 123 | slideAnchor: string, slideIndex: number) => void; 124 | @Input() public mnFullpageOnSlideLeave: (anchorLink: string, 125 | index: number, slideIndex: number, direction: string, 126 | nextSlideIndex: number) => void; 127 | 128 | /** 129 | * --------------------------------------------------------------------------- 130 | * | Class properties | 131 | * --------------------------------------------------------------------------- 132 | */ 133 | 134 | private _el: ElementRef; 135 | 136 | /** 137 | * Static method for option name retrieving 138 | * 139 | * @param property this class property name 140 | * @returns {string} FullpageOption class option (property) name 141 | */ 142 | private static extractName(property: string) { 143 | return property[MnFullpageDirective.propertyPrefix.length].toLowerCase() 144 | + property.substring(MnFullpageDirective.propertyPrefix.length + 1); 145 | } 146 | 147 | /** 148 | * Default public constructor 149 | * 150 | * @param el element where directive is placed on 151 | */ 152 | public constructor(el: ElementRef) { 153 | this._el = el; 154 | } 155 | 156 | /** 157 | * Perform actions on init 158 | */ 159 | ngAfterViewInit(): void { 160 | /** 161 | * Initialize options object with default (empty) 162 | * values if it doesn't exist 163 | */ 164 | if (!this.options) { 165 | this.options = new MnFullpageOptions(); 166 | } 167 | 168 | /** 169 | * Iterate over all properties of directive class 170 | */ 171 | for (const property of Object.keys(this)) { 172 | /** 173 | * If property name doesn't start with 'fullpage' prefix (it is stored in 174 | * FullpageDirective.propertyPrefix static property) then skip this property and 175 | * continue the cycle 176 | */ 177 | if (!property.startsWith(MnFullpageDirective.propertyPrefix)) { 178 | continue; 179 | } 180 | 181 | /** 182 | * Extract option name from the property name 183 | * 184 | * @type {string} option name 185 | */ 186 | const option = MnFullpageDirective.extractName(property); 187 | 188 | /** 189 | * If options is already defined skip it 190 | */ 191 | if (this.options[option]) { 192 | continue; 193 | } 194 | 195 | /** 196 | * Set property value to the options object property 197 | */ 198 | this.options[option] = this[property]; 199 | } 200 | 201 | /** 202 | * Enable fullpage for the element 203 | */ 204 | setTimeout(() => { 205 | ($)(this._el.nativeElement).fullpage(this.options); 206 | }, 300); 207 | } 208 | 209 | } 210 | -------------------------------------------------------------------------------- /src/app/fullpage/mnFullpage-options.class.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Meiblorn (Vadim Fedorenko) on 15/05/16. 3 | */ 4 | 5 | export class MnFullpageOptions { 6 | 7 | /** 8 | * Notice: 9 | * 10 | * All documentation was taken from https://github.com/alvarotrigo/fullPage.js 11 | */ 12 | 13 | /** 14 | * Index signature 15 | */ 16 | [key: string]: any; 17 | 18 | /** 19 | * --------------------------------------------------------------------------- 20 | * | Navigation | 21 | * --------------------------------------------------------------------------- 22 | */ 23 | 24 | /** 25 | * A selector can be used to specify the menu to link with 26 | * the sections. This way the scrolling of the sections will activate 27 | * the corresponding element in the menu using the class active. This won't 28 | * generate a menu but will just add the active class to the element in the 29 | * given menu with the corresponding anchor links. In order to link the elements 30 | * of the menu with the sections, an HTML 5 data-tag (data-menuanchor) will be 31 | * needed to use with the same anchor links as used within the sections. 32 | * 33 | * @default false 34 | */ 35 | public menu: string; 36 | 37 | /** 38 | * Determines whether anchors in the URL will have any effect at 39 | * all in the plugin. You can still using anchors internally for 40 | * your own functions and callbacks, but they won't have any effect 41 | * in the scrolling of the site. Useful if you want to combine fullPage.js 42 | * with other plugins using anchor in the URL. 43 | */ 44 | public lockAnchors: boolean; 45 | 46 | /** 47 | * Defines the anchor links (#example) to be shown on the URL 48 | * for each section. Anchors value should be unique. The position 49 | * of the anchors in the array will define to which sections the 50 | * anchor is applied. (second position for second section and so on). 51 | * Using anchors forward and backward navigation will also be possible 52 | * through the browser. This option also allows users to bookmark a 53 | * specific section or slide. Be careful! anchors can not have the same 54 | * value as any ID element on the site (or NAME element for IE). Now 55 | * anchors can be defined directly in the HTML structure by using the 56 | * attribute data-anchor as explained here. 57 | * 58 | * @default [] 59 | */ 60 | public anchors: Array; 61 | 62 | /** 63 | * If set to true, it will show a navigation bar made up of small circles. 64 | * 65 | * @default false 66 | */ 67 | public navigation: boolean; 68 | 69 | /** 70 | * It can be set to left or right and defines which 71 | * position the navigation bar will be shown (if using one). 72 | * 73 | * @default none 74 | */ 75 | public navigationPosition: string; 76 | 77 | /** 78 | * Defines the tooltips to show for the navigation circles 79 | * in case they are being used. 80 | * 81 | * @default [] 82 | */ 83 | public navigationTooltips: Array; 84 | 85 | /** 86 | * Shows a persistent tooltip for the actively viewed section 87 | * in the vertical navigation. 88 | * 89 | * @default false 90 | */ 91 | public showActiveTooltip: boolean; 92 | 93 | /** 94 | * If set to true it will show a navigation bar made up of 95 | * small circles for each landscape slider on the site. 96 | * 97 | * @default false 98 | */ 99 | public slidesNavigation: boolean; 100 | 101 | /** 102 | * Defines the position for the landscape navigation bar for sliders. 103 | * Admits top and bottom as values. You may want to modify the CSS styles 104 | * to determine the distance from the top or bottom as well as any other 105 | * style such as color. 106 | * 107 | * @default bottom 108 | */ 109 | public slidesNavPosition: string; 110 | 111 | /** 112 | * --------------------------------------------------------------------------- 113 | * | Scrolling | 114 | * --------------------------------------------------------------------------- 115 | */ 116 | 117 | /** 118 | * Defines whether to use JavaScript or CSS3 transforms to scroll within 119 | * sections and slides. Useful to speed up the movement in tablet and mobile 120 | * devices with browsers supporting CSS3. If this option is set to true and 121 | * the browser doesn't support CSS3, a jQuery fallback will be used instead. 122 | * 123 | * @default true 124 | */ 125 | public css3: boolean; 126 | 127 | /** 128 | * Speed in milliseconds for the scrolling transitions. 129 | * 130 | * @default 700 131 | */ 132 | public scrollingSpeed: number; 133 | 134 | /** 135 | * Defines whether to use the "automatic" scrolling or the "normal" one. 136 | * It also has affects the way the sections fit in the browser/device window 137 | * in tablets and mobile phones. 138 | * 139 | * @default true 140 | */ 141 | public autoScrolling: boolean; 142 | 143 | /** 144 | * If fitToSection is set to true, this delays the fitting 145 | * by the configured milliseconds. 146 | * 147 | * @default 1000 148 | */ 149 | public fitToSection: boolean; 150 | 151 | /** 152 | * If fitToSection is set to true, this delays the fitting by 153 | * the configured milliseconds. 154 | * 155 | * @default 1000 156 | */ 157 | public fitToSectionDelay: number; 158 | 159 | /** 160 | * Determines whether to use scrollbar for the site or not. 161 | * In case of using scroll bar, the autoScrolling functionality 162 | * will still working as expected. The user will also be free to 163 | * scroll the site with the scroll bar and fullPage.js will fit the 164 | * section in the screen when scrolling finishes. 165 | * 166 | * @default false 167 | */ 168 | public scrollBar: boolean; 169 | 170 | /** 171 | * Defines the transition effect to use for the vertical 172 | * and horizontal scrolling. It requires the file 173 | * vendors/jquery.easings.min.js or jQuery UI for using some 174 | * of its transitions. Other libraries could be used instead. 175 | * 176 | * @default easeInOutCubic 177 | */ 178 | public easing: string; 179 | 180 | /** 181 | * Defines the transition effect to use in case of using css3:true. 182 | * You can use the pre-defined ones (such as linear, ease-out...) or 183 | * create your own ones using the cubic-bezier function. You might 184 | * want to use Matthew Lein CSS Easing Animation Tool for it. 185 | * 186 | * @default ease 187 | */ 188 | public easingcss3: string; 189 | 190 | /** 191 | * Defines whether scrolling down in the last section should scroll 192 | * to the first one or not 193 | * 194 | * @default false 195 | */ 196 | public loopBottom: boolean; 197 | 198 | /** 199 | * Defines whether scrolling up in the first section should 200 | * scroll to the last one or not. 201 | * 202 | * @default false 203 | */ 204 | public loopTop: boolean; 205 | 206 | /** 207 | * Defines whether horizontal sliders will loop after reaching 208 | * the last or previous slide or not. 209 | * 210 | * @default true 211 | */ 212 | public loopHorizontal: boolean; 213 | 214 | /** 215 | * Defines whether scrolling down in the last section should 216 | * scroll down to the first one or not, and if scrolling up in 217 | * the first section should scroll up to the last one or not. 218 | * Not compatible with loopTop or loopBottom. 219 | * 220 | * @default false 221 | */ 222 | public continuousVertical: boolean; 223 | 224 | /** 225 | * If you want to avoid the auto scroll when scrolling over 226 | * some elements, this is the option you need to use. (useful 227 | * for maps, scrolling divs etc.) It requires a string with the 228 | * jQuery selectors for those elements. 229 | * 230 | * @default null 231 | */ 232 | public normalScrollElements: string; 233 | 234 | /** 235 | * Defines whether or not to create a scroll for the section 236 | * in case its content is bigger than the height of it. When 237 | * set to true, your content will be wrapped by the plugin. 238 | * Consider using delegation or load your other scripts in the 239 | * afterRender callback. In case of setting it to true, it requires 240 | * the vendor plugin jquery.slimscroll.min and it should be 241 | * loaded before the fullPage.js plugin. 242 | * 243 | * @default false 244 | */ 245 | public scrollOverflow: boolean; 246 | 247 | /** 248 | * Defines a percentage of the browsers window width/height, and 249 | * how far a swipe must measure for navigating to the next 250 | * section / slide 251 | * 252 | * @default 5 253 | */ 254 | public touchSensitivity: number; 255 | 256 | /** 257 | * Defines the threshold for the number of hops up the html node 258 | * tree Fullpage will test to see if normalScrollElements is a match 259 | * to allow scrolling functionality on divs on a touch device. 260 | * 261 | * @default 5 262 | */ 263 | public normalScrollElementTouchThreshold: number; 264 | 265 | /** 266 | * --------------------------------------------------------------------------- 267 | * | Accessibility | 268 | * --------------------------------------------------------------------------- 269 | */ 270 | 271 | /** 272 | * Defines if the content can be navigated using the keyboard 273 | * 274 | * @default true 275 | */ 276 | public keyboardScrolling: boolean; 277 | 278 | /** 279 | * Defines whether the load of the site when given an 280 | * anchor (#) will scroll with animation to its destination or 281 | * will directly load on the given section. 282 | * 283 | * @default true 284 | */ 285 | public animateAnchor: boolean; 286 | 287 | /** 288 | * Defines whether to push the state of the site to 289 | * the browser's history. When set to true each 290 | * section/slide of the site will act as a new page 291 | * and the back and forward buttons of the browser will 292 | * scroll the sections/slides to reach the previous or next 293 | * state of the site. When set to false, the URL will keep 294 | * changing but will have no effect ont he browser's history. 295 | * This option is automatically turned off when using 296 | * autoScrolling:false. 297 | * 298 | * @default true 299 | */ 300 | public recordHistory: boolean; 301 | 302 | /** 303 | * --------------------------------------------------------------------------- 304 | * | Design | 305 | * --------------------------------------------------------------------------- 306 | */ 307 | 308 | /** 309 | * Determines whether to use control arrows for the 310 | * slides to move right or left. 311 | * 312 | * @default true 313 | */ 314 | public controlArrows: boolean; 315 | 316 | /** 317 | * Vertically centering of the content within sections. 318 | * When set to true, your content will be wrapped by the plugin. 319 | * Consider using delegation or load your other scripts 320 | * in the afterRender callback. 321 | * 322 | * @default true 323 | */ 324 | public verticalCentered: boolean; 325 | 326 | /** 327 | * Whether you want to resize the text when the window is resized. 328 | * 329 | * @default false 330 | */ 331 | public resize: boolean; 332 | 333 | /** 334 | * Define the CSS background-color property for each section. 335 | * 336 | * @default none 337 | */ 338 | public sectionsColor: Array; 339 | 340 | /** 341 | * Defines the top padding for each section with 342 | * a numerical value and its measure 343 | * (paddingTop: '10px', paddingTop: '10em'...) 344 | * Useful in case of using a fixed header. 345 | * 346 | * @default 0 347 | */ 348 | public paddingTop: string; 349 | 350 | /** 351 | * Defines the bottom padding for each section with 352 | * a numerical value and its measure 353 | * (paddingBottom: '10px', paddingBottom: '10em'...). 354 | * Useful in case of using a fixed footer. 355 | * 356 | * @default 0 357 | */ 358 | public paddingBottom: string; 359 | 360 | /** 361 | * Defines which elements will be taken off the scrolling 362 | * structure of the plugin which is necessary when using 363 | * the css3 option to keep them fixed. It requires a string 364 | * with the jQuery selectors for those elements. 365 | * 366 | * @default null 367 | */ 368 | public fixedElements: string; 369 | 370 | /** 371 | * A normal scroll (autoScrolling:false) will be used under 372 | * the defined width in pixels. A class fp-responsive is added 373 | * to the body tag in case the user wants to use it for his own 374 | * responsive CSS. For example, if set to 900, whenever the 375 | * browser's width is less than 900 the plugin will scroll like 376 | * a normal site. 377 | * 378 | * @default 0 379 | */ 380 | public responsiveWidth: number; 381 | 382 | /** 383 | * A normal scroll (autoScrolling:false) will be used under 384 | * the defined height in pixels. A class fp-responsive is added 385 | * to the body tag in case the user wants to use it for his own 386 | * responsive CSS. For example, if set to 900, whenever the browser's 387 | * height is less than 900 the plugin will scroll 388 | * like a normal site. 389 | * 390 | * @default 0 391 | */ 392 | public responsiveHeight: number; 393 | 394 | /** 395 | * Defines the jQuery selector used for the plugin sections. 396 | * It might need to be changed sometimes to avoid problem with 397 | * other plugins using the same selectors as fullpage.js. 398 | * 399 | * @default .section 400 | */ 401 | public sectionSelector: string; 402 | 403 | /** 404 | * Defines the jQuery selector used for the plugin slides. 405 | * It might need to be changed sometimes to avoid problem 406 | * with other plugins using the same selectors as fullpage.js. 407 | * 408 | * @default .slide 409 | */ 410 | public slideSelector: string; 411 | 412 | /** 413 | * --------------------------------------------------------------------------- 414 | * | Callbacks | 415 | * --------------------------------------------------------------------------- 416 | */ 417 | 418 | /** 419 | * Callback fired once the sections have been loaded, after 420 | * the scrolling has ended. 421 | * 422 | * Parameters: 423 | * - anchorLink: anchorLink corresponding to the section. 424 | * - index: index of the section. Starting from 1. 425 | * 426 | * In case of not having anchorLinks defined in the plugin the 427 | * index parameter would be the only one to use. 428 | */ 429 | public afterLoad: (anchorLink: string, index: number) => void; 430 | 431 | /** 432 | * This callback is fired once the user leaves a section, 433 | * in the transition to the new section. Returning false will 434 | * cancel the move before it takes place. 435 | * 436 | * Parameters: 437 | * - index: index of the leaving section. Starting from 1. 438 | * - nextIndex: index of the destination section. Starting from 1. 439 | * - direction: it will take the values up or down depending 440 | * on the scrolling direction. 441 | * 442 | */ 443 | public onLeave: (index: number, nextIndex: number, direction: string) => void; 444 | 445 | /** 446 | * This callback is fired just after the structure of 447 | * the page is generated. This is the callback you want to 448 | * use to initialize other plugins or fire any code which requires 449 | * the document to be ready (as this plugin modifies 450 | * the DOM to create the resulting structure). 451 | */ 452 | public afterRender: () => void; 453 | 454 | /** 455 | * This callback is fired after resizing the browser's window. 456 | * Just after the sections are resized. 457 | */ 458 | public afterResize: () => void; 459 | 460 | /** 461 | * Callback fired once the slide of a section have been loaded, after 462 | * the scrolling has ended. 463 | * 464 | * Parameters: 465 | * - anchorLink: anchorLink corresponding to the section. 466 | * - index: index of the section. Starting from 1. 467 | * - slideAnchor: anchor corresponding to the slide (in case there is) 468 | * - slideIndex: index of the slide. Starting from 1. (the default slide 469 | * doesn't count as slide, but as a section) 470 | * 471 | * In case of not having anchorLinks defined for the slide or slides the 472 | * slideIndex parameter would be the only one to use. 473 | */ 474 | public afterSlideLoad: (anchorLink: string, index: number, 475 | slideAnchor: string, slideIndex: number) => void; 476 | 477 | /** 478 | * This callback is fired once the user leaves an slide to go to another, 479 | * in the transition to the new slide. Returning false will cancel the move 480 | * before it takes place. 481 | * 482 | * Parameters: 483 | * - anchorLink: anchorLink corresponding to the section. 484 | * - index: index of the section. Starting from 1. 485 | * - slideIndex: index of the slide. Starting from 0. 486 | * - direction: takes the values right or left depending on the scrolling 487 | * direction. 488 | * - nextSlideIndex: index of the destination slide. Starting from 0. 489 | * 490 | */ 491 | public onSlideLeave: (anchorLink: string, index: number, slideIndex: number, 492 | direction: string, nextSlideIndex: number) => void; 493 | 494 | /** 495 | * Public default constructor 496 | * 497 | * @param options options js-object 498 | */ 499 | constructor(options?: Object) { 500 | if (options) { 501 | (Object).assign(this, options); 502 | } 503 | } 504 | 505 | } 506 | -------------------------------------------------------------------------------- /meepo_hunli/template/mobile/3rdpartylicenses.txt: -------------------------------------------------------------------------------- 1 | core-js@2.5.3 2 | MIT 3 | Copyright (c) 2014-2017 Denis Pushkarev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | zone.js@0.8.20 24 | MIT 25 | The MIT License 26 | 27 | Copyright (c) 2016 Google, Inc. 28 | 29 | Permission is hereby granted, free of charge, to any person obtaining a copy 30 | of this software and associated documentation files (the "Software"), to deal 31 | in the Software without restriction, including without limitation the rights 32 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 33 | copies of the Software, and to permit persons to whom the Software is 34 | furnished to do so, subject to the following conditions: 35 | 36 | The above copyright notice and this permission notice shall be included in 37 | all copies or substantial portions of the Software. 38 | 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 45 | THE SOFTWARE. 46 | 47 | webpack@3.10.0 48 | MIT 49 | Copyright JS Foundation and other contributors 50 | 51 | Permission is hereby granted, free of charge, to any person obtaining 52 | a copy of this software and associated documentation files (the 53 | 'Software'), to deal in the Software without restriction, including 54 | without limitation the rights to use, copy, modify, merge, publish, 55 | distribute, sublicense, and/or sell copies of the Software, and to 56 | permit persons to whom the Software is furnished to do so, subject to 57 | the following conditions: 58 | 59 | The above copyright notice and this permission notice shall be 60 | included in all copies or substantial portions of the Software. 61 | 62 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 63 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 64 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 65 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 66 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 67 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 68 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 69 | 70 | ms@2.0.0 71 | MIT 72 | The MIT License (MIT) 73 | 74 | Copyright (c) 2016 Zeit, Inc. 75 | 76 | Permission is hereby granted, free of charge, to any person obtaining a copy 77 | of this software and associated documentation files (the "Software"), to deal 78 | in the Software without restriction, including without limitation the rights 79 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 80 | copies of the Software, and to permit persons to whom the Software is 81 | furnished to do so, subject to the following conditions: 82 | 83 | The above copyright notice and this permission notice shall be included in all 84 | copies or substantial portions of the Software. 85 | 86 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 87 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 88 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 89 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 90 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 91 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 92 | SOFTWARE. 93 | 94 | process@0.11.10 95 | MIT 96 | (The MIT License) 97 | 98 | Copyright (c) 2013 Roman Shtylman 99 | 100 | Permission is hereby granted, free of charge, to any person obtaining 101 | a copy of this software and associated documentation files (the 102 | 'Software'), to deal in the Software without restriction, including 103 | without limitation the rights to use, copy, modify, merge, publish, 104 | distribute, sublicense, and/or sell copies of the Software, and to 105 | permit persons to whom the Software is furnished to do so, subject to 106 | the following conditions: 107 | 108 | The above copyright notice and this permission notice shall be 109 | included in all copies or substantial portions of the Software. 110 | 111 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 112 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 113 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 114 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 115 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 116 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 117 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 118 | 119 | parseuri@0.0.5 120 | MIT 121 | The MIT License (MIT) 122 | 123 | Copyright (c) 2014 Gal Koren 124 | 125 | Permission is hereby granted, free of charge, to any person obtaining a copy 126 | of this software and associated documentation files (the "Software"), to deal 127 | in the Software without restriction, including without limitation the rights 128 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 129 | copies of the Software, and to permit persons to whom the Software is 130 | furnished to do so, subject to the following conditions: 131 | 132 | The above copyright notice and this permission notice shall be included in 133 | all copies or substantial portions of the Software. 134 | 135 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 136 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 137 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 138 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 139 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 140 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 141 | THE SOFTWARE. 142 | 143 | engine.io-client@3.1.5 144 | MIT 145 | (The MIT License) 146 | 147 | Copyright (c) 2014-2015 Automattic 148 | 149 | Permission is hereby granted, free of charge, to any person obtaining 150 | a copy of this software and associated documentation files (the 151 | 'Software'), to deal in the Software without restriction, including 152 | without limitation the rights to use, copy, modify, merge, publish, 153 | distribute, sublicense, and/or sell copies of the Software, and to 154 | permit persons to whom the Software is furnished to do so, subject to 155 | the following conditions: 156 | 157 | The above copyright notice and this permission notice shall be 158 | included in all copies or substantial portions of the Software. 159 | 160 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 161 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 162 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 163 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 164 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 165 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 166 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 167 | 168 | base64-arraybuffer@0.1.5 169 | MIT 170 | MIT 171 | 172 | component-emitter@1.2.1 173 | MIT 174 | (The MIT License) 175 | 176 | Copyright (c) 2014 Component contributors 177 | 178 | Permission is hereby granted, free of charge, to any person 179 | obtaining a copy of this software and associated documentation 180 | files (the "Software"), to deal in the Software without 181 | restriction, including without limitation the rights to use, 182 | copy, modify, merge, publish, distribute, sublicense, and/or sell 183 | copies of the Software, and to permit persons to whom the 184 | Software is furnished to do so, subject to the following 185 | conditions: 186 | 187 | The above copyright notice and this permission notice shall be 188 | included in all copies or substantial portions of the Software. 189 | 190 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 191 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 192 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 193 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 194 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 195 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 196 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 197 | OTHER DEALINGS IN THE SOFTWARE. 198 | 199 | after@0.8.2 200 | MIT 201 | MIT 202 | 203 | socket.io-client@2.0.4 204 | MIT 205 | The MIT License (MIT) 206 | 207 | Copyright (c) 2014 Guillermo Rauch 208 | 209 | 210 | Permission is hereby granted, free of charge, to any person obtaining a copy 211 | of this software and associated documentation files (the "Software"), to deal 212 | in the Software without restriction, including without limitation the rights 213 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 214 | copies of the Software, and to permit persons to whom the Software is 215 | furnished to do so, subject to the following conditions: 216 | 217 | The above copyright notice and this permission notice shall be included in 218 | all copies or substantial portions of the Software. 219 | 220 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 221 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 222 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 223 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 224 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 225 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 226 | THE SOFTWARE. 227 | 228 | @angular/core@5.2.7 229 | MIT 230 | MIT 231 | 232 | has-cors@1.1.0 233 | MIT 234 | MIT 235 | 236 | yeast@0.1.2 237 | MIT 238 | The MIT License (MIT) 239 | 240 | Copyright (c) 2015 Unshift.io, Arnout Kazemier, the Contributors. 241 | 242 | Permission is hereby granted, free of charge, to any person obtaining a copy 243 | of this software and associated documentation files (the "Software"), to deal 244 | in the Software without restriction, including without limitation the rights 245 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 246 | copies of the Software, and to permit persons to whom the Software is 247 | furnished to do so, subject to the following conditions: 248 | 249 | The above copyright notice and this permission notice shall be included in all 250 | copies or substantial portions of the Software. 251 | 252 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 253 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 254 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 255 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 256 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 257 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 258 | SOFTWARE. 259 | 260 | parseqs@0.0.5 261 | MIT 262 | The MIT License (MIT) 263 | 264 | Copyright (c) 2015 Gal Koren 265 | 266 | Permission is hereby granted, free of charge, to any person obtaining a copy 267 | of this software and associated documentation files (the "Software"), to deal 268 | in the Software without restriction, including without limitation the rights 269 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 270 | copies of the Software, and to permit persons to whom the Software is 271 | furnished to do so, subject to the following conditions: 272 | 273 | The above copyright notice and this permission notice shall be included in 274 | all copies or substantial portions of the Software. 275 | 276 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 277 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 278 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 279 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 280 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 281 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 282 | THE SOFTWARE. 283 | 284 | meepo-common@1.1.8 285 | MIT 286 | MIT 287 | 288 | debug@2.6.9 289 | MIT 290 | (The MIT License) 291 | 292 | Copyright (c) 2014 TJ Holowaychuk 293 | 294 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 295 | and associated documentation files (the 'Software'), to deal in the Software without restriction, 296 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 297 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 298 | subject to the following conditions: 299 | 300 | The above copyright notice and this permission notice shall be included in all copies or substantial 301 | portions of the Software. 302 | 303 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 304 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 305 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 306 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 307 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 308 | 309 | @angular/platform-browser@5.2.7 310 | MIT 311 | MIT 312 | 313 | @angular/common@5.2.7 314 | MIT 315 | MIT 316 | 317 | @angular/service-worker@5.2.7 318 | MIT 319 | MIT 320 | 321 | ng-antd-mobile-notice-bar@1.0.0-alpha.0 322 | MIT 323 | MIT 324 | 325 | ng-antd-mobile@1.0.5 326 | MIT 327 | MIT 328 | 329 | @types/socket.io-client@1.4.32 330 | MIT 331 | MIT License 332 | 333 | Copyright (c) Microsoft Corporation. All rights reserved. 334 | 335 | Permission is hereby granted, free of charge, to any person obtaining a copy 336 | of this software and associated documentation files (the "Software"), to deal 337 | in the Software without restriction, including without limitation the rights 338 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 339 | copies of the Software, and to permit persons to whom the Software is 340 | furnished to do so, subject to the following conditions: 341 | 342 | The above copyright notice and this permission notice shall be included in all 343 | copies or substantial portions of the Software. 344 | 345 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 346 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 347 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 348 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 349 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 350 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 351 | SOFTWARE 352 | 353 | css-loader@0.28.10 354 | MIT 355 | Copyright JS Foundation and other contributors 356 | 357 | Permission is hereby granted, free of charge, to any person obtaining 358 | a copy of this software and associated documentation files (the 359 | 'Software'), to deal in the Software without restriction, including 360 | without limitation the rights to use, copy, modify, merge, publish, 361 | distribute, sublicense, and/or sell copies of the Software, and to 362 | permit persons to whom the Software is furnished to do so, subject to 363 | the following conditions: 364 | 365 | The above copyright notice and this permission notice shall be 366 | included in all copies or substantial portions of the Software. 367 | 368 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 369 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 370 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 371 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 372 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 373 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 374 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 375 | 376 | meepo-utils@1.0.0-alpha.0 377 | MIT 378 | MIT 379 | 380 | @angular/cdk@5.2.3 381 | MIT 382 | The MIT License 383 | 384 | Copyright (c) 2018 Google LLC. 385 | 386 | Permission is hereby granted, free of charge, to any person obtaining a copy 387 | of this software and associated documentation files (the "Software"), to deal 388 | in the Software without restriction, including without limitation the rights 389 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 390 | copies of the Software, and to permit persons to whom the Software is 391 | furnished to do so, subject to the following conditions: 392 | 393 | The above copyright notice and this permission notice shall be included in 394 | all copies or substantial portions of the Software. 395 | 396 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 397 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 398 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 399 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 400 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 401 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 402 | THE SOFTWARE. 403 | 404 | @angular/platform-browser-dynamic@5.2.7 405 | MIT 406 | MIT 407 | 408 | has-binary2@1.0.2 409 | MIT 410 | The MIT License (MIT) 411 | 412 | Copyright (c) 2014 Kevin Roark 413 | 414 | Permission is hereby granted, free of charge, to any person obtaining a copy of 415 | this software and associated documentation files (the "Software"), to deal in 416 | the Software without restriction, including without limitation the rights to 417 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 418 | the Software, and to permit persons to whom the Software is furnished to do so, 419 | subject to the following conditions: 420 | 421 | The above copyright notice and this permission notice shall be included in all 422 | copies or substantial portions of the Software. 423 | 424 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 425 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 426 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 427 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 428 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 429 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 430 | 431 | to-array@0.1.4 432 | MIT 433 | MIT 434 | 435 | classnames@2.2.5 436 | MIT 437 | The MIT License (MIT) 438 | 439 | Copyright (c) 2016 Jed Watson 440 | 441 | Permission is hereby granted, free of charge, to any person obtaining a copy 442 | of this software and associated documentation files (the "Software"), to deal 443 | in the Software without restriction, including without limitation the rights 444 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 445 | copies of the Software, and to permit persons to whom the Software is 446 | furnished to do so, subject to the following conditions: 447 | 448 | The above copyright notice and this permission notice shall be included in all 449 | copies or substantial portions of the Software. 450 | 451 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 452 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 453 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 454 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 455 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 456 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 457 | SOFTWARE. 458 | 459 | backo2@1.0.2 460 | MIT 461 | MIT 462 | 463 | normalize.css@7.0.0 464 | MIT 465 | # The MIT License (MIT) 466 | 467 | Copyright © Nicolas Gallagher and Jonathan Neal 468 | 469 | Permission is hereby granted, free of charge, to any person obtaining a copy of 470 | this software and associated documentation files (the "Software"), to deal in 471 | the Software without restriction, including without limitation the rights to 472 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 473 | of the Software, and to permit persons to whom the Software is furnished to do 474 | so, subject to the following conditions: 475 | 476 | The above copyright notice and this permission notice shall be included in all 477 | copies or substantial portions of the Software. 478 | 479 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 480 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 481 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 482 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 483 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 484 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 485 | SOFTWARE. 486 | 487 | weui@1.1.2 488 | MIT 489 | MIT --------------------------------------------------------------------------------