├── .angular-cli.json ├── .editorconfig ├── .eslintrc.bak ├── .gitignore ├── .vscode └── launch.json ├── README.md ├── SqlScript ├── nodejs.sql └── nodejs_home.zip ├── doc └── img │ ├── callDelete.png │ ├── callFileUpload.png │ ├── callFuZhi.png │ ├── callInsert.png │ ├── callJudgeCondition.png │ ├── callQuery.png │ ├── callSaveCache.png │ ├── callThirdPartApi.png │ ├── callTran.png │ ├── callTranCommit.png │ └── callUpdate.png ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.e2e.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── protractor.conf.js ├── server ├── ManagerQueue.js ├── ca │ ├── www.other.org.crt │ ├── www.other.org.csr │ └── www.other.org.key ├── ctrl_es6 │ ├── ApiHelper.js │ ├── DbHelper.js │ ├── DealBusiness.js │ ├── UserInfo.js │ ├── __ThirdPartyApi.js │ ├── index.js │ └── webapi.js ├── favicon.ico ├── index.api.js ├── index.js └── lib │ ├── Log.js │ └── Utility.js ├── src ├── app │ ├── Common │ │ └── Utility.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── app.router.ts │ ├── components │ │ ├── ComponentTools.ts │ │ ├── Confirm │ │ │ ├── Confirm.html │ │ │ ├── Confirm.scss │ │ │ └── Confirm.ts │ │ ├── Core.ts │ │ ├── Index.ts │ │ ├── Map │ │ │ ├── Core.ts │ │ │ ├── Index.ts │ │ │ ├── PlaceItem │ │ │ │ ├── PlaceItem.html │ │ │ │ ├── PlaceItem.scss │ │ │ │ └── PlaceItem.ts │ │ │ └── marker │ │ │ │ ├── marker.html │ │ │ │ ├── marker.scss │ │ │ │ └── marker.ts │ │ ├── Scroll │ │ │ ├── Scroll.html │ │ │ ├── Scroll.scss │ │ │ └── Scroll.ts │ │ ├── __defref │ │ │ ├── defref.html │ │ │ ├── defref.scss │ │ │ └── defref.ts │ │ ├── apiitem │ │ │ ├── apiitem.html │ │ │ ├── apiitem.scss │ │ │ └── apiitem.ts │ │ ├── model │ │ │ ├── ActionSheet │ │ │ │ ├── ActionSheet.html │ │ │ │ ├── ActionSheet.scss │ │ │ │ └── ActionSheet.ts │ │ │ ├── Core.ts │ │ │ ├── Dialog │ │ │ │ ├── Dialog.html │ │ │ │ ├── Dialog.scss │ │ │ │ └── Dialog.ts │ │ │ └── Loading │ │ │ │ ├── Loading.html │ │ │ │ ├── Loading.scss │ │ │ │ └── Loading.ts │ │ ├── navbar │ │ │ ├── navbar.component.html │ │ │ ├── navbar.component.scss │ │ │ ├── navbar.component.spec.ts │ │ │ └── navbar.component.ts │ │ └── rule │ │ │ ├── RuleInfo.html │ │ │ ├── RuleInfo.scss │ │ │ ├── RuleInfo.ts │ │ │ ├── RuleItem.html │ │ │ ├── RuleItem.scss │ │ │ └── RuleItem.ts │ ├── containers │ │ ├── Core.ts │ │ ├── Index.ts │ │ ├── app.animations.ts │ │ ├── baidu-map │ │ │ ├── Index.ts │ │ │ ├── MyJoinPlace │ │ │ │ ├── MyJoinPlace.html │ │ │ │ ├── MyJoinPlace.scss │ │ │ │ └── MyJoinPlace.ts │ │ │ ├── MyPlaceList │ │ │ │ ├── MyPlaceList.html │ │ │ │ ├── MyPlaceList.scss │ │ │ │ └── MyPlaceList.ts │ │ │ ├── baidu-map.html │ │ │ ├── baidu-map.scss │ │ │ ├── baidu-map.spec.ts │ │ │ └── baidu-map.ts │ │ ├── base.component.ts │ │ ├── home │ │ │ ├── home.component.html │ │ │ ├── home.component.scss │ │ │ ├── home.component.spec.ts │ │ │ └── home.component.ts │ │ ├── members │ │ │ ├── members.component.html │ │ │ ├── members.component.scss │ │ │ ├── members.component.spec.ts │ │ │ └── members.component.ts │ │ ├── my-component │ │ │ ├── my-component.component.html │ │ │ ├── my-component.component.scss │ │ │ ├── my-component.component.spec.ts │ │ │ └── my-component.component.ts │ │ ├── not-found │ │ │ ├── not-found.component.html │ │ │ ├── not-found.component.scss │ │ │ ├── not-found.component.spec.ts │ │ │ └── not-found.component.ts │ │ └── product │ │ │ ├── product.component.html │ │ │ ├── product.component.scss │ │ │ ├── product.component.spec.ts │ │ │ └── product.component.ts │ ├── helpers │ │ ├── ApiClient.ts │ │ ├── ClientMiddleware.ts │ │ └── Core.ts │ ├── manage │ │ ├── Core.ts │ │ ├── Index.ts │ │ ├── dashboard │ │ │ ├── Address │ │ │ │ ├── Address.html │ │ │ │ ├── Address.scss │ │ │ │ └── Address.ts │ │ │ ├── Contacts │ │ │ │ ├── Contacts.html │ │ │ │ ├── Contacts.scss │ │ │ │ └── Contacts.ts │ │ │ ├── Dashboard.html │ │ │ ├── Dashboard.scss │ │ │ ├── Dashboard.ts │ │ │ ├── Index.ts │ │ │ └── Place │ │ │ │ ├── Index.ts │ │ │ │ ├── Place.html │ │ │ │ ├── Place.scss │ │ │ │ ├── Place.ts │ │ │ │ └── PlaceList │ │ │ │ ├── PlaceList.html │ │ │ │ ├── PlaceList.scss │ │ │ │ └── PlaceList.ts │ │ ├── login │ │ │ ├── login.html │ │ │ ├── login.scss │ │ │ └── login.ts │ │ ├── register │ │ │ ├── register.html │ │ │ ├── register.scss │ │ │ └── register.ts │ │ └── userlist │ │ │ ├── userlist.html │ │ │ ├── userlist.scss │ │ │ └── userlist.ts │ ├── manageapi │ │ ├── Core.ts │ │ ├── Index.ts │ │ └── apilist │ │ │ ├── apilist.html │ │ │ ├── apilist.scss │ │ │ └── apilist.ts │ └── service │ │ ├── ApiManager.ts │ │ ├── BaiduMapService.ts │ │ ├── CommonService.ts │ │ ├── Core.ts │ │ ├── Demo.ts │ │ ├── ServiceHelper.ts │ │ ├── UserInfo.ts │ │ └── index.ts ├── assets │ ├── .gitkeep │ └── img │ │ ├── car-icon.png │ │ └── person-icon.png ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.scss ├── test.ts ├── tsconfig.app.json ├── tsconfig.spec.json └── typings.d.ts ├── temp.txt ├── tsconfig.json └── tslint.json /.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "project": { 4 | "name": "travel-together" 5 | }, 6 | "apps": [ 7 | { 8 | "root": "src", 9 | "outDir": "dist", 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 | "environmentSource": "environments/environment.ts", 26 | "environments": { 27 | "dev": "environments/environment.ts", 28 | "prod": "environments/environment.prod.ts" 29 | } 30 | } 31 | ], 32 | "e2e": { 33 | "protractor": { 34 | "config": "./protractor.conf.js" 35 | } 36 | }, 37 | "lint": [ 38 | { 39 | "project": "src/tsconfig.app.json" 40 | }, 41 | { 42 | "project": "src/tsconfig.spec.json" 43 | }, 44 | { 45 | "project": "e2e/tsconfig.e2e.json" 46 | } 47 | ], 48 | "test": { 49 | "karma": { 50 | "config": "./karma.conf.js" 51 | } 52 | }, 53 | "defaults": { 54 | "styleExt": "scss", 55 | "component": {} 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.eslintrc.bak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/.eslintrc.bak -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | .history/ 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | runtime/ 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | testem.log 34 | /typings 35 | 36 | # e2e 37 | /e2e/*.js 38 | /e2e/*.map 39 | 40 | # System Files 41 | .DS_Store 42 | Thumbs.db 43 | .history/ 44 | public/ 45 | yarn.lock 46 | package-lock.json -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 以学习相关的 Node.js 调试属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "protocol": "auto", 11 | "name": "启动程序", 12 | "program": "${workspaceRoot}/server/index.js", 13 | "outFiles": [ 14 | "${workspaceRoot}/out/**/*.js" 15 | ], 16 | "env": { 17 | "PORT": "30001", 18 | "APIPORT": "30081" 19 | } 20 | }, 21 | { 22 | "type": "node", 23 | "request": "launch", 24 | "name": "NodeJsEs6", 25 | "protocol": "auto", 26 | "program": "${workspaceRoot}/server/nodejs_es6.js", 27 | "env": { 28 | "PORT": "10001", 29 | "DEVPORT": "10081" 30 | } 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TravelTogether 2 | 3 | ## !!注意!! 4 | 由于用的是http2请求,证书是在一个网站 https://csr.chinassl.net/index.html 里申请的。因此,如果用IE进行调试的话,后台NodeJs服务器会报异常,google浏览器没有发现问题。所有写的prototype.的方法在IE10下找不到,服务器就报异常了; 5 | ``` code 6 | http.ServerResponse.prototype.Send = function (data) { 7 | this.write(JSON.stringify(data)); 8 | this.end(); 9 | }; 10 | 11 | -- 12 | 其实他地方调用的方法时如: Response.Send({}); IE10来的请求就报说找不到 Send()这个方法,google浏览器就可以正常使用。 13 | ``` 14 | 15 | ## 如果数据库连接数量超过最大值,可以修改ManagerQueue.js Next()方法里 setTimeout,添加点时间来进行缓冲一下。 16 | 17 | 18 | ## 批量文件上传时个数据表文件为: 19 | ``` sql 20 | CREATE TABLE `xtn_sys_file` ( 21 | `FileId` int(11) NOT NULL AUTO_INCREMENT, 22 | `FileType` varchar(50) DEFAULT NULL COMMENT '文件类型', 23 | `FileName` varchar(150) DEFAULT NULL COMMENT '文件名称', 24 | `FilePath` varchar(200) DEFAULT NULL COMMENT '文件路径', 25 | `FileSize` int(11) DEFAULT NULL COMMENT '文件大小', 26 | `Status` tinyint(1) DEFAULT '1', 27 | `CreateTime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 28 | PRIMARY KEY (`Id`) 29 | ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COMMENT='文件系统表'; 30 | 31 | ``` 32 | - 文件上传成功后返回,上传成功的ID 33 | 34 | # 后台接口配置系统 35 | ## 已经完成的功能 36 | - 查询 37 | ![call query](doc/img/callQuery.png) 38 | - 更新 39 | ![call update](doc/img/callUpdate.png) 40 | - 插入 41 | ![call insert](doc/img/callInsert.png) 42 | - 删除 43 | ![call delete](doc/img/callDelete.png) 44 | - 开始事务 45 | ![call tran](doc/img/callTran.png) 46 | - 提交事务 47 | ![call tran commit](doc/img/callTranCommit.png) 48 | - 条件判断 49 | ![call judge condition](doc/img/callJudgeCondition.png) 50 | - 保存到缓存 51 | ![call call save](doc/img/callSaveCache.png) 52 | - 赋值操作 53 | ![call fu zhi](doc/img/callFuZhi.png) 54 | - 主子关系 55 | - 验证码 56 | - 文件上传 57 | ![call fileupload](doc/img/callFileUpload.png) 58 | - 调用第三方API,配置如下。 59 | ![call third part api](doc/img/callThirdPartApi.png) 60 | ----- 61 | 62 | 63 | 64 | 项目的依赖安装 65 | ```bash 66 | npm install 67 | ``` 68 | 项目启动 69 | ```bash 70 | npm run dev 71 | ``` 72 | 单独启动前端的话 73 | ``` 74 | npm run start 75 | ``` 76 | 单独启动后台接口 77 | ```bash 78 | npm run start-dev 79 | ``` 80 | 81 | 如果专门调试接口的话,还是分别单独启动为好. 82 | 83 | ## nodejs.sql MySql 5.7以上版本。 84 | 由于本试例中要用到MYSQL数据,所在在项目的根目录中有一个nodejs.sql的文件。将结构导入到数据库中即可,数据库版本是5.7以的,因为里面有一个sys_rule表里的Content存放的是JSON,只有5.7才能支持JSON字段。 85 | 86 | ## 修改数据库连接 87 | /server/ctrl_es6/DbHelper.js里33行左右 88 | ```javascript 89 | /** 90 | * 创建一个资源池 91 | * 92 | * @memberof MySqlHelper 93 | */ 94 | __CreatePool() { 95 | this.pool = mysql.createPool({ 96 | connectionLimit: 10, 97 | host: 'localhost', // 数据库连接 98 | user: 'liaohb', // 数据库名用户名 99 | password: 'xiaotuni', // 密码 100 | database: 'nodejs' // 表空间 101 | }); 102 | 103 | this.pool.on('connection', (connection)=> { 104 | // connection.query('SET SESSION auto_increment_increment=1') 105 | }); 106 | this.pool.on('release', (connection)=> { 107 | // console.log('Connection %d released', connection.threadId); 108 | }); 109 | } 110 | 111 | ``` 112 | 113 | # 组件 114 | ------ 115 | ## Scroll.ts有个问题 116 | 117 | ``` 118 | const __ctrl = document.body.children[0].children[1]; 119 | const { scrollTop, scrollHeight } = __ctrl; 120 | ``` 121 | - 在SlideNextPage() 方法里,上面这行代码,为什么这样写,页不写成 document.body呢?是因为,我在做路由界面切换动画时,设置了position: 'fixed' ,如果这种切换动画话,就可以改成 122 | ``` 123 | const { scrollTop, scrollHeight } = document.body; 124 | ``` 125 | 126 | 127 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.0.3. 128 | 129 | ## Development server 130 | 131 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 132 | 133 | ## Code scaffolding 134 | 135 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|module`. 136 | 137 | ## Build 138 | 139 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. 140 | 141 | ## Running unit tests 142 | 143 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 144 | 145 | ## Running end-to-end tests 146 | 147 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 148 | Before running the tests make sure you are serving the app via `ng serve`. 149 | 150 | ## Further help 151 | 152 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 153 | -------------------------------------------------------------------------------- /SqlScript/nodejs_home.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/SqlScript/nodejs_home.zip -------------------------------------------------------------------------------- /doc/img/callDelete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callDelete.png -------------------------------------------------------------------------------- /doc/img/callFileUpload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callFileUpload.png -------------------------------------------------------------------------------- /doc/img/callFuZhi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callFuZhi.png -------------------------------------------------------------------------------- /doc/img/callInsert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callInsert.png -------------------------------------------------------------------------------- /doc/img/callJudgeCondition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callJudgeCondition.png -------------------------------------------------------------------------------- /doc/img/callQuery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callQuery.png -------------------------------------------------------------------------------- /doc/img/callSaveCache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callSaveCache.png -------------------------------------------------------------------------------- /doc/img/callThirdPartApi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callThirdPartApi.png -------------------------------------------------------------------------------- /doc/img/callTran.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callTran.png -------------------------------------------------------------------------------- /doc/img/callTranCommit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callTranCommit.png -------------------------------------------------------------------------------- /doc/img/callUpdate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/doc/img/callUpdate.png -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { TravelTogetherPage } from './app.po'; 2 | 3 | describe('travel-together App', () => { 4 | let page: TravelTogetherPage; 5 | 6 | beforeEach(() => { 7 | page = new TravelTogetherPage(); 8 | }); 9 | 10 | it('should display message saying app works', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('app works!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class TravelTogetherPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "node" 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/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 | files: [ 19 | { pattern: './src/test.ts', watched: false } 20 | ], 21 | preprocessors: { 22 | './src/test.ts': ['@angular/cli'] 23 | }, 24 | mime: { 25 | 'text/x-typescript': ['ts','tsx'] 26 | }, 27 | coverageIstanbulReporter: { 28 | reports: [ 'html', 'lcovonly' ], 29 | fixWebpackSourcePaths: true 30 | }, 31 | angularCli: { 32 | environment: 'dev' 33 | }, 34 | reporters: config.angularCli && config.angularCli.codeCoverage 35 | ? ['progress', 'coverage-istanbul'] 36 | : ['progress', 'kjhtml'], 37 | port: 9876, 38 | colors: true, 39 | logLevel: config.LOG_INFO, 40 | autoWatch: true, 41 | browsers: ['Chrome'], 42 | singleRun: false 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "travel-together", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start-dev": "better-npm-run start-dev", 8 | "watch-client": "better-npm-run watch-client", 9 | "dev": "concurrent --kill-others \"npm run start-dev\" \"npm run watch-client\"", 10 | "start": "ng serve --port 3000", 11 | "start:dev": "better-npm-run start:dev", 12 | "build": "ng build", 13 | "test": "ng test", 14 | "lint": "ng lint", 15 | "e2e": "ng e2e" 16 | }, 17 | "betterScripts": { 18 | "watch-client": { 19 | "command": "ng serve", 20 | "env": { 21 | "NODE_PATH": "./src", 22 | "NODE_ENV": "development ", 23 | "PORT": 30000, 24 | "APIPORT": 30001 25 | } 26 | }, 27 | "start-dev": { 28 | "command": "supervisor ./server/index.js", 29 | "env": { 30 | "NODE_PATH": "./server", 31 | "NODE_ENV": "development ", 32 | "PORT": 30000, 33 | "DEVPORT": 30080, 34 | "APIPORT": 30081 35 | } 36 | }, 37 | "start:dev": { 38 | "command": "ng serve", 39 | "env": { 40 | "NODE_PATH": "./src", 41 | "NODE_ENV": "development", 42 | "PORT": 30000, 43 | "APIPORT": 30001 44 | } 45 | } 46 | }, 47 | "private": true, 48 | "dependencies": { 49 | "@angular/common": "^4.0.0", 50 | "@angular/compiler": "^4.0.0", 51 | "@angular/core": "^4.0.0", 52 | "@angular/forms": "^4.0.0", 53 | "@angular/http": "^4.0.0", 54 | "@angular/platform-browser": "^4.0.0", 55 | "@angular/platform-browser-dynamic": "^4.0.0", 56 | "@angular/router": "^4.0.0", 57 | "core-js": "^2.4.1", 58 | "rxjs": "^5.1.0", 59 | "supervisor": "^0.12.0", 60 | "zone.js": "^0.8.4" 61 | }, 62 | "devDependencies": { 63 | "@angular/animations": "^4.1.3", 64 | "@angular/cli": "1.0.3", 65 | "@angular/compiler-cli": "^4.0.0", 66 | "@types/jasmine": "2.5.38", 67 | "@types/node": "~6.0.60", 68 | "better-npm-run": "0.0.15", 69 | "code-point-at": "^1.1.0", 70 | "codelyzer": "~2.0.0", 71 | "concurrent": "^0.3.2", 72 | "concurrently": "^3.4.0", 73 | "crypto-js": "^3.1.9-1", 74 | "events": "^1.1.1", 75 | "fibers": "^2.0.0", 76 | "http2": "^3.3.6", 77 | "jasmine-core": "~2.5.2", 78 | "jasmine-spec-reporter": "~3.2.0", 79 | "karma": "~1.4.1", 80 | "karma-chrome-launcher": "~2.1.1", 81 | "karma-cli": "~1.0.1", 82 | "karma-coverage-istanbul-reporter": "^0.2.0", 83 | "karma-jasmine": "~1.1.0", 84 | "karma-jasmine-html-reporter": "^0.2.2", 85 | "mongodb": "^2.2.28", 86 | "mysql": "^2.13.0", 87 | "protractor": "~5.1.0", 88 | "querystringify": "^1.0.0", 89 | "superagent": "^3.5.2", 90 | "svg-captcha": "^1.3.9", 91 | "ts-node": "~2.0.0", 92 | "tslint": "~4.5.0", 93 | "typescript": "~2.2.0" 94 | }, 95 | "main": "index.js", 96 | "author": "xiaotuni " 97 | } 98 | -------------------------------------------------------------------------------- /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 | beforeLaunch: function() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | }, 27 | onPrepare() { 28 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /server/ManagerQueue.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 队列管理,主要是用来处理量请求时 3 | * 由于要调用数据库,大量的请求,在调用的时候 4 | * 前面调用 .end方法,后面就会出现在pool close的情况。 5 | * 6 | * 也许还有其它好的办法,目前就想到了这种方法。 7 | * 8 | * @class ManagerQueue 9 | */ 10 | class ManagerQueue { 11 | 12 | /** 13 | * 创建一个带参数的构造函数 14 | * @param {any} MySqlHelper mysql操作类 15 | * @memberof ManagerQueue 16 | */ 17 | constructor(MySqlHelper) { 18 | this._Queue = []; 19 | this.IsLock = false; 20 | this.MySqlHelper = MySqlHelper; 21 | } 22 | 23 | /** 24 | * 添加请求到队列里 25 | * 26 | * @param {any} options 参数 27 | * @memberof ManagerQueue 28 | */ 29 | AddQueue(options) { 30 | this._Queue.push(options); 31 | this.GetQueueLength(); 32 | if (!this.IsLock) { 33 | this.IsLock = true; 34 | const args = this._Queue.shift(); 35 | setTimeout(() => { 36 | this.NextQueue(args); 37 | }, 0); 38 | } 39 | } 40 | 41 | /** 42 | * 下一个 43 | * 44 | * @returns 45 | * @memberof ManagerQueue 46 | */ 47 | Next() { 48 | const { _Queue } = this; 49 | if (_Queue.length === 0) { 50 | this.IsLock = false; 51 | // console.log('---------队列处理完了------'); 52 | return; 53 | } 54 | this.GetQueueLength(); 55 | setTimeout(() => { 56 | this.NextQueue(_Queue.shift()); 57 | }, 0); 58 | } 59 | 60 | /** 61 | * 执行下一请求 62 | * 63 | * @param {any} args 64 | * @returns 65 | * @memberof ManagerQueue 66 | */ 67 | NextQueue(args) { 68 | const { ApiInfo, request, response, params, data, token, TokenCollection, func, ctrl, methodInfo } = args; 69 | const newArgs = Object.assign({}, args); 70 | delete newArgs.request; 71 | delete newArgs.response; 72 | 73 | if (func) { 74 | func.apply(ctrl, [request, response, newArgs]); 75 | return; 76 | } 77 | const _db = new this.MySqlHelper(); // 实例化一个数据库操作类 78 | _db.__TokenCollection__ = TokenCollection; 79 | ApiInfo.DealBusiness.Process(_db, request, response, newArgs); 80 | } 81 | 82 | /** 83 | * 84 | * 85 | * @memberof ManagerQueue 86 | */ 87 | GetQueueLength() { 88 | // console.log('---------队列大小为:【%d】--------', this._Queue.length); 89 | return this._Queue.length; 90 | } 91 | } 92 | 93 | module.exports = ManagerQueue; -------------------------------------------------------------------------------- /server/ca/www.other.org.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID4jCCAsqgAwIBAgICCpMwDQYJKoZIhvcNAQELBQAwczELMAkGA1UEBhMCQ04x 3 | EDAOBgNVBAgMB1RpYW5qaW4xEDAOBgNVBAcMB1RpYW5qaW4xFTATBgNVBAoMDENI 4 | SU5BU1NMIEluYzEpMCcGA1UEAwwgQ0hJTkFTU0wgQ2VydGlmaWNhdGlvbiBBdXRo 5 | b3JpdHkwHhcNMTcwNjEyMDcwOTI1WhcNMTgwNjEyMDcwOTI1WjB1MQswCQYDVQQG 6 | EwJDTjEQMA4GA1UECAwHYmVpamluZzEMMAoGA1UECgwDeHRuMQswCQYDVQQLDAJJ 7 | VDEWMBQGA1UEAwwNd3d3Lm90aGVyLm9yZzEhMB8GCSqGSIb3DQEJARYSeGlhb3R1 8 | bmlAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoE2Z 9 | tyIUxjK66AmH/tUXIC17YDFlDCTHoW6pq5n418uEljMmCgn8zNt7eIeHxrutqTQo 10 | f3JwV3Z8RQwCs8gsziZUFPq70wJ7uN+f1wSBAVn82KY6Dz9SdTFhUgvVvhMzzFXH 11 | gclV1UA7rjG8rcCfgZVEMzMvvl2WLPQ/HyFikR9RKrMFdlmUJJYAUbtFvnRdCb/a 12 | YKC23kQ6+1V+AY8N3e2UsJYd6ViFE5Wy1Rd2BF2jg0/zeNNWx0ZKFIGvYvpnieZS 13 | 8TQgMX8LYMG7+W/OxEan4nhAfpsSfHlDeQqPKsG+jsq8vALQYXhM+pkZ20USkyyC 14 | uO3IZJbkKJ2WgC/YMwIDAQABo34wfDAJBgNVHRMEAjAAMC8GCWCGSAGG+EIBDQQi 15 | FiBDSElOQVNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAdBgNVHQ4EFgQUYznn 16 | 2F9aaVXw7yWNxqChngvGqtYwHwYDVR0jBBgwFoAUXB8j+sjhITHC2Df2iPzSb8JU 17 | QzMwDQYJKoZIhvcNAQELBQADggEBABbd3zmrJ4GTZWsxQ8h8GgUIioZZbTS1Vzwo 18 | 9SNfrTugCDJmrNMakgMFDUFce4OwfhQV04e3FfTwHV+fJY07mfC+PLbN9KrY8+5Z 19 | cO5ZR8+gbIk4vAFLg3Di1uLcTIK2s17BL/T46l02otMHcGcsDYjIMgge5WsYj/H2 20 | FcPt8+h+RTEMOGxnrMOCpViHeZZCZQi3EoTcXRZQ82cRtt8xlO7zbC9AvwO+1FHE 21 | lqXyh5xYiPaef03Z4J4qmoS7CIYHAf7ewDyIj5Tgw1jJ009raEaY4gVs/NrAxddZ 22 | AsI3ocFaRudj8CFd8MhvuOlDBx7qx/OoQrhcbjZaMzid6TKFbVk= 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /server/ca/www.other.org.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICzTCCAbUCAQAwgYcxCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdiZWlqaW5nMRAw 3 | DgYDVQQHDAdiZWlqaW5nMQwwCgYDVQQKDAN4dG4xCzAJBgNVBAsMAklUMRYwFAYD 4 | VQQDDA13d3cub3RoZXIub3JnMSEwHwYJKoZIhvcNAQkBFhJ4aWFvdHVuaUBnbWFp 5 | bC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgTZm3IhTGMrro 6 | CYf+1RcgLXtgMWUMJMehbqmrmfjXy4SWMyYKCfzM23t4h4fGu62pNCh/cnBXdnxF 7 | DAKzyCzOJlQU+rvTAnu435/XBIEBWfzYpjoPP1J1MWFSC9W+EzPMVceByVXVQDuu 8 | MbytwJ+BlUQzMy++XZYs9D8fIWKRH1EqswV2WZQklgBRu0W+dF0Jv9pgoLbeRDr7 9 | VX4Bjw3d7ZSwlh3pWIUTlbLVF3YEXaODT/N401bHRkoUga9i+meJ5lLxNCAxfwtg 10 | wbv5b87ERqfieEB+mxJ8eUN5Co8qwb6Oyry8AtBheEz6mRnbRRKTLIK47chkluQo 11 | nZaAL9gzAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAQ5Uw44iVz7SR+xWsh5i3 12 | JeHpZ9zIG+XFTfCWBgwwAK8GkOfaYeZrR7AtlcQdASuN19TT+f2XG3marOy16HCl 13 | ho57RJh0t/7llVdh+T48QiN1WPxuJSrnN0L2yYR4zESW/4NEwNHAt5vSCq3T9C9l 14 | vJlzQL5cFy2WkSg/QOaHNLwMUheu2JrY+Ygr1OyY5SF/N6UlD8539CzAkx9p2zca 15 | ocrGq6kkX71FxoZRMFQbzASZvVnkwRoVuHlifGvRCFQ5oDsKf5KG0C0UzO2UDM8J 16 | Rqk+5X+OlHXAfnLfmxAsiDYdD8HIgik4nWMpgbDBzvvDUZCcATsn6rf129QhITv4 17 | uw== 18 | -----END CERTIFICATE REQUEST----- 19 | -------------------------------------------------------------------------------- /server/ca/www.other.org.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCgTZm3IhTGMrro 3 | CYf+1RcgLXtgMWUMJMehbqmrmfjXy4SWMyYKCfzM23t4h4fGu62pNCh/cnBXdnxF 4 | DAKzyCzOJlQU+rvTAnu435/XBIEBWfzYpjoPP1J1MWFSC9W+EzPMVceByVXVQDuu 5 | MbytwJ+BlUQzMy++XZYs9D8fIWKRH1EqswV2WZQklgBRu0W+dF0Jv9pgoLbeRDr7 6 | VX4Bjw3d7ZSwlh3pWIUTlbLVF3YEXaODT/N401bHRkoUga9i+meJ5lLxNCAxfwtg 7 | wbv5b87ERqfieEB+mxJ8eUN5Co8qwb6Oyry8AtBheEz6mRnbRRKTLIK47chkluQo 8 | nZaAL9gzAgMBAAECggEAJvb12DfmiM6n8+LtNZoiRuYHSTh4cV03URwPDfEdNYb4 9 | sXG5W1NWKY1oE8IN1Nalva058tCkUf4w8q+asIyFp45Vfcv8f6vo2uUwexlTKjrv 10 | ZNHy5uXjay0XlNPfnpYYTyDCn9+Kh41XdF4OmMVrgBoCO9fDUSh6am7sMOryhIeP 11 | ozV9CXyu2Tl0SRbvnuA8Ed0W2UcgAPU6zdtCXB9xQpXxqbmwpGJf0ZoN8FCSVRAF 12 | rV6T1YyMR+xe6MrgyRnrqQcvp5vZbywgeqmSnYGrIoJJDAUX+EtkDIH25DUojq0l 13 | Ajj+WnrN7uQogDo5aRHmJuDGEucVAF10QYDq9sA0YQKBgQDUGAv7XKEjUoeWgEJ1 14 | sBKFBKv7ldoeRXFDr8TLaEMTYcIWH7VAqkHxBuTRK5RdAFZonSZqVXW2MjKXr0Pv 15 | zYM2T00TNE6qFN/oQ+hCGHqyL8TdGesIcRw7iJtVMKMeOg107c9HEeFuSYMU8bei 16 | Ji2fkPfYhTto7ZNZ8Qob+UzMGQKBgQDBfOQqvVpT3QLqNhWlwxx4HFQsFZl7cbBr 17 | LUFvd41k/6NHShU/Xtvi5BE23GolbYpJoRaFcKApPJVWtjTy2TTn9xb42uQ5KCKQ 18 | 0/xkdKvSG4HEYeylBOyYJscGMVOIqaVpXJ5/7QdPfTMI+YGAZY3/EJ86U15sVHzL 19 | 5am2YMgQKwKBgArcYGCy0Z2ZcFAIqV6VcZ1WK+hqOA0sySwKKC2yXRz0+JdhcEqr 20 | bU0GaVk8vhA1IDejNIBld+2ojGawFu6Eu59gWDYPi6eyAfVG5PHdhwrw30fjN+Hq 21 | yONTj4DBSNkXZ/EA7IhbJgwbv5am+hxXkCaHqelwiSZKZC1K5pWgIoqhAoGAb31K 22 | cAIpwTcRjelaMeiqR99y9PABP2s0D53FHbiSpcbTy6k5cwlyxFtMPANnumdTDrge 23 | pQdPklNRbeSRv/k+jgcHmp9ucCzbNf6gaTX9J5UoAgO2+yNKPSXi+oODsbSnFn4C 24 | 6o2m77uho6M5ZsWdu4JVbaNKPju0qTyNvQQpY38CgYApx2tRfQpFHrSWPC6z3b/n 25 | 2kaOi1YqrqhSLqFLsT5YfzZi+AjWosZ9aTMc1t2MO7fcqMLTI+pnylQ4vG/ZK/8T 26 | mgPsB/5CzvIbZNF6dmFf7Z28flozF5hKsABXAaRRXBk9ENs4B6EMKm42bo0VFMA9 27 | 6iTWjytY76obVO6vEjql8Q== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /server/ctrl_es6/ApiHelper.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const vCode = require('svg-captcha'); 3 | const Utility = require('../lib/Utility'); 4 | 5 | class ApiHelper { 6 | 7 | constructor() { 8 | 9 | } 10 | 11 | post_api(request, response, options) { 12 | response.SendOk(); 13 | } 14 | 15 | 16 | put_api(request, response, options) { 17 | response.SendOk(); 18 | } 19 | 20 | delete_api(request, response, options) { 21 | response.SendOk(); 22 | } 23 | 24 | get_captcha(req, res, options) { 25 | const captcha = vCode.create({ fontSize: 50, width: 100 }); 26 | const exp = new Date(); 27 | const a = new Date(exp.getTime() + 1000 * 60 * 10); 28 | Utility.ConstItem.CaptchaInfo[captcha.text] = a; 29 | res.Send(captcha.data); 30 | } 31 | 32 | get_captchaCode(req, res, options) { 33 | const captcha = vCode.create({ fontSize: 50, width: 100, height: 40 }); 34 | const exp = new Date(); 35 | const date = new Date(exp.getTime() + 1000 * 60 * 10); 36 | // 其实可以将验证码进行MD5加密一下。 37 | Utility.ConstItem.CaptchaInfo[captcha.text.toLocaleLowerCase()] = date; 38 | res.SendImgSvg(captcha.data); 39 | } 40 | 41 | post_fileupload(req, res, options) { 42 | console.log('--------file upload--------'); 43 | 44 | const __fileName = 'file_name_' + new Date().getTime() + '.png'; 45 | const { data } = options; 46 | fs.appendFileSync('./public/image/' + __fileName, data, 'buffer'); 47 | res.SendOk(); 48 | } 49 | 50 | 51 | post_filesupload(req, res, options) { 52 | console.log('--------file list upload--------'); 53 | 54 | const __fileName = 'file_name_' + new Date().getTime() + '.png'; 55 | const { data } = options; 56 | fs.appendFileSync('./public/image/' + __fileName, data, 'buffer'); 57 | res.SendOk(); 58 | } 59 | 60 | get_async(req, res, options) { 61 | let aa = async () => { 62 | console.log('-------------0-------'); 63 | const fun1 = await function () { 64 | return new Promise((resolve, reject) => { 65 | console.log('------1--func1------'); 66 | resolve('哈哈'); 67 | }); 68 | }; 69 | const fun2 = await function () { 70 | console.log('-----2--func2-----'); 71 | return '方法2返回的值' 72 | } 73 | let result = fun1(); 74 | console.log('----------下面是调用fun1 返回的数据-----'); 75 | console.log(result); 76 | console.log('----------下面是调用fun2-----'); 77 | let result1 = fun2(); 78 | console.log('----------fun2 返回值为:---------', result1); 79 | } 80 | 81 | aa(); 82 | 83 | res.Send({ code: 200, msg: 'async' }); 84 | } 85 | } 86 | 87 | module.exports = ApiHelper; -------------------------------------------------------------------------------- /server/ctrl_es6/UserInfo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 用户信息类 3 | * 4 | * @class UserInfo 5 | */ 6 | class UserInfo { 7 | constructor(DbHelper, Utility) { 8 | this.DbHelper = DbHelper; 9 | this.Utility = Utility; 10 | } 11 | 12 | } 13 | 14 | module.exports = UserInfo; 15 | -------------------------------------------------------------------------------- /server/ctrl_es6/__ThirdPartyApi.js: -------------------------------------------------------------------------------- 1 | const httpClient = require('http'); 2 | const querystring = require('querystring'); 3 | const url = require('url'); 4 | const path = require('path'); 5 | const Utility = require('../lib/Utility'); 6 | 7 | class ThirdPartyApi { 8 | constructor(dbHelper) { 9 | this.DbAccess = dbHelper; 10 | } 11 | 12 | CallApi(args, Success, Error) { 13 | const { Rule, Options } = args; 14 | const { id, name, apiCall, isMergeOption } = Rule; 15 | const { Url, Method, ApiBodyParams, ApiHeaderParams } = apiCall; 16 | const urlInfo = url.parse(Url, true); 17 | const { hostname, path, port, protocol } = urlInfo; 18 | 19 | const _options = { host: hostname, port, path, method: Method, headers: {} }; 20 | if (ApiHeaderParams) { 21 | ApiHeaderParams.forEach((hInfo) => { 22 | const { ParamName, ParamValue, IsFixedValue } = hInfo; 23 | if (ParamValue || ParamValue === false || ParamValue === 0) { 24 | _options.headers[ParamName] = IsFixedValue === true ? ParamValue : Options[ParamValue]; 25 | } 26 | }); 27 | } 28 | const postData = {}; 29 | if (ApiBodyParams) { 30 | ApiBodyParams.forEach((bInfo) => { 31 | const { ParamName, ParamValue, IsFixedValue } = bInfo; 32 | if (ParamValue || ParamValue === false || ParamValue === 0) { 33 | postData[ParamName] = IsFixedValue === true ? ParamValue : Options[ParamValue]; 34 | } 35 | }); 36 | } 37 | _options.headers['Content-Type'] = 'application/json'; 38 | const hClientRequest = httpClient.request(_options, (res) => { 39 | // res.setEncoding('utf8'); 40 | let finalData = ""; 41 | res.on("data", function (data) { 42 | finalData += data.toString(); 43 | }); 44 | 45 | res.on("end", function () { 46 | console.log(finalData); 47 | const _result = JSON.parse(finalData); 48 | Object.assign(Options, _result || {}); 49 | Options.Result[id] = { __name: name, result: _result }; 50 | Success && Success(); 51 | }); 52 | }); 53 | const _m = Method.toLocaleLowerCase(); 54 | const _methodList = ['get', 'delete']; // 请求的时候,不能写数据的。否则会报socket hand up错误。 55 | if (!_methodList.includes(_m)) { 56 | hClientRequest.write(JSON.stringify(postData)); 57 | } 58 | hClientRequest.on('error', (e) => { 59 | Error && Error(e); 60 | }); 61 | hClientRequest.end(); 62 | } 63 | } 64 | 65 | module.exports = ThirdPartyApi; -------------------------------------------------------------------------------- /server/ctrl_es6/index.js: -------------------------------------------------------------------------------- 1 | const webapi = require('./webapi'); 2 | const DealBusiness = require('./DealBusiness'); 3 | 4 | module.exports = { 5 | webapi, 6 | DealBusiness: new DealBusiness() 7 | } -------------------------------------------------------------------------------- /server/ctrl_es6/webapi.js: -------------------------------------------------------------------------------- 1 | const DbHelper = require('./DbHelper'); 2 | const Utility = require('../lib/Utility'); 3 | const UserInfo = require('./UserInfo'); 4 | const ApiHelper = require('./ApiHelper'); 5 | module.exports = { 6 | userinfo: new UserInfo(DbHelper, Utility), 7 | apihelper: new ApiHelper(), 8 | }; -------------------------------------------------------------------------------- /server/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/server/favicon.ico -------------------------------------------------------------------------------- /server/index.api.js: -------------------------------------------------------------------------------- 1 | // const http = require('http2'); 2 | const http = require('http'); 3 | const util = require('util'); 4 | const querystring = require('querystring'); 5 | const url = require('url'); 6 | const path = require('path'); 7 | const fs = require('fs'); 8 | const api = require('./ctrl_es6/index'); 9 | const MySqlHelper = require('./ctrl_es6/DbHelper'); 10 | const ManagerQueue = require('./ManagerQueue'); 11 | const formidable = require('formidable'); 12 | 13 | /** 14 | * 为什么在这里引用呢,JS是从上向下找的,如果在send()之前没有找到 __MQ变量的话,会报错误 15 | * 在每个请求处理完Send()之后,要调用 __MQ.Next()方法。 16 | * 所在就在这里引用进来。 17 | */ 18 | const __MQ = new ManagerQueue(MySqlHelper); 19 | 20 | /** 21 | * 日期格式化 22 | * var time1 = new Date().Format(“yyyy-MM-dd”); 23 | * var time2 = new Date().Format(“yyyy-MM-dd hh:mm:ss”); 24 | * var time2 = new Date().Format(“yyyy-MM-dd hh:mm:ss.S”); 25 | * @param fmt 26 | * @returns {*} 27 | * @constructor 28 | */ 29 | Date.prototype.Format = function (fmt) { //author: meizz 30 | var o = { 31 | "M+": this.getMonth() + 1, //月份 32 | "d+": this.getDate(), //日 33 | "h+": this.getHours(), //小时 34 | "m+": this.getMinutes(), //分 35 | "s+": this.getSeconds(), //秒 36 | "q+": Math.floor((this.getMonth() + 3) / 3), //季度 37 | "S": this.getMilliseconds() //毫秒 38 | }; 39 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 40 | for (var k in o) 41 | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 42 | return fmt; 43 | } 44 | 45 | /** 46 | * 发送内容到界面上去. 47 | * @param data 48 | */ 49 | http.ServerResponse.prototype.Send = function (data) { 50 | this.write(JSON.stringify(data)); 51 | this.end(); 52 | // 处理下一个请求。 53 | __MQ.Next(); 54 | }; 55 | http.ServerResponse.prototype.SendImgSvg = function (data) { 56 | this.setHeader('Content-Type', 'image/svg+xml'); 57 | this.write(String(data)); 58 | this.end(); 59 | // 处理下一个请求。 60 | __MQ.Next(); 61 | } 62 | http.ServerResponse.prototype.SendOk = function () { 63 | this.Send({ msg: 'ok' }); 64 | }; 65 | http.ServerResponse.prototype.Send_404 = function (data) { 66 | this.statusCode = 404; 67 | this.Send(data); 68 | }; 69 | http.ServerResponse.prototype.Send401 = function (data) { 70 | this.statusCode = 401; 71 | this.Send({ msg: data }); 72 | }; 73 | http.ServerResponse.prototype.Send_500 = function (data) { 74 | this.statusCode = 500; 75 | this.Send(data); 76 | }; 77 | http.ServerResponse.prototype.SendError = function (data) { 78 | const { code } = data; 79 | this.statusCode = code || 400; 80 | this.Send(data); 81 | }; 82 | 83 | 84 | class Server { 85 | constructor() { } 86 | 87 | CreateServer(port) { 88 | const __key = '/ca/www.other.org.key'; 89 | const __crt = '/ca/www.other.org.crt'; 90 | const __keys = [path.join('.', 'server', __key), '.' + __key]; 91 | const __crts = [path.join('.', 'server', __crt), '.' + __crt]; 92 | const extKey = __keys.filter((p) => { 93 | if (fs.existsSync(p)) { 94 | return p; 95 | } 96 | }); 97 | const extCrt = __crts.filter((p) => { 98 | if (fs.existsSync(p)) { 99 | return p; 100 | } 101 | }); 102 | 103 | const options = { 104 | key: fs.readFileSync(extKey[0]), //读取key 105 | cert: fs.readFileSync(extCrt[0]) //读取crt 106 | }; 107 | // console.log('--------options-------'); 108 | // console.log(options); 109 | // console.log('--------options-------'); 110 | http.createServer((req, res) => { 111 | const r = new routes(req, res); 112 | r.initHeader(); 113 | }).listen(port || 20000); 114 | console.log('http://127.0.0.1:%d', port || 20000) 115 | } 116 | } 117 | 118 | class routes { 119 | constructor(req, res) { 120 | this.ApiInfo = api; 121 | this.res = res; 122 | this.req = req; 123 | } 124 | 125 | initHeader() { 126 | this.res.setHeader("Content-Type", "application/json;charset=utf-8"); 127 | this.res.setHeader("Access-Control-Allow-Origin", "*"); 128 | this.res.setHeader("access-control-allow-headers", "x-pingother, origin, x-requested-with, content-type, accept, token, xiaotuni,systemdate,sessionid"); 129 | this.res.setHeader("access-control-allow-methods", "GET, POST, PUT, DELETE, OPTIONS"); 130 | this.res.setHeader("Access-Control-Expose-Headers", "date, token,systemdate,sessionid"); 131 | this.res.setHeader('systemdate', new Date().getTime()); 132 | const { method } = this.req; 133 | if (method && method === 'OPTIONS') { 134 | this.res.end(); 135 | return; 136 | } 137 | console.log('-------------header---start--------'); 138 | console.log(this.req.headers); 139 | console.log('-------------header---end----------'); 140 | this.processRequestMethod(method); 141 | } 142 | 143 | processRequestMethod(method) { 144 | const PathInfo = path.parse(this.req.url); 145 | if (!this.judgeIsCallApi(PathInfo)) { 146 | return; 147 | } 148 | this.Method = method.toLocaleLowerCase(); 149 | this.parseUrlParams(); 150 | this.__ProcessApi(PathInfo); 151 | } 152 | 153 | __ProcessApi(PathInfo) { 154 | const methodInfo = { pathname: this.UrlInfo.pathname, method: this.Method }; 155 | const { func, ctrl } = this.__FindMethod(PathInfo) || {}; 156 | const __self = this; 157 | const { TokenCollection } = MySqlHelper; 158 | const args = { 159 | request: this.req, response: this.res, params: this.QueryParams, 160 | token: this.token, TokenCollection, methodInfo, ApiInfo: this.ApiInfo, func, ctrl 161 | }; 162 | 163 | const res = this.res; 164 | const form = new formidable.IncomingForm(); 165 | form.multiples = true; // 多文件 166 | form.keepExtensions = true;//是否包含文件后缀 167 | form.parse(this.req, (err, fields, files) => { 168 | if (err) { 169 | res.SendError({ msg: err.message }); 170 | return; 171 | } 172 | args.data = fields; 173 | args.files = files; 174 | if (func) { 175 | func.apply(ctrl, [request, response, newArgs]); 176 | return; 177 | } 178 | console.log('--------------------data------------------------'); 179 | const __NewData = fields; 180 | const __ReturnData = {}; 181 | Object.keys(__NewData).forEach((key) => { 182 | // const Value = __NewData[key]; 183 | __ReturnData['XTN_' + key] = __NewData[key]; 184 | }); 185 | console.log(__ReturnData); 186 | console.log('--------------------data------------------------'); 187 | res.Send(__ReturnData); 188 | // res.Send_404({ status: 404, msg: '接口没有找到' }); 189 | }); 190 | } 191 | 192 | judgeIsCallApi(PathInfo) { 193 | if (PathInfo.ext === '') { 194 | return true; 195 | } 196 | let charset = "binary"; 197 | switch (PathInfo.ext) { 198 | case ".js": 199 | this.res.writeHead(200, { "Content-Type": "text/javascript" }); 200 | break; 201 | case ".css": 202 | this.res.writeHead(200, { "Content-Type": "text/css" }); 203 | break; 204 | case ".gif": 205 | charset = "binary"; 206 | this.res.writeHead(200, { "Content-Type": "image/gif" }); 207 | break; 208 | case ".jpg": 209 | charset = "binary"; 210 | this.res.writeHead(200, { "Content-Type": "image/jpeg" }); 211 | break; 212 | case ".png": 213 | charset = "binary"; 214 | this.res.writeHead(200, { "Content-Type": "image/png" }); 215 | break; 216 | default: 217 | this.res.writeHead(200, { "Content-Type": "application/octet-stream" }); 218 | } 219 | 220 | const { dir, ext, name } = PathInfo; 221 | const __abs = path.join(dir, name + ext); 222 | const _pathInfo = [path.join('./server/', __abs), path.join('.', __abs)]; 223 | const __self = this; 224 | let __fileIsExist = false; 225 | for (let i = 0; i < _pathInfo.length; i++) { 226 | const dir = _pathInfo[i]; 227 | __fileIsExist = fs.existsSync(dir); 228 | if (__fileIsExist) { 229 | fs.readFile(dir, (err, data) => { 230 | if (err) { 231 | __self.res.Send({ code: -1, msg: err.toString() }); 232 | } else { 233 | __self.res.write(data, charset); 234 | } 235 | __self.res.end(); 236 | }); 237 | return false; 238 | } 239 | } 240 | if (!__fileIsExist) { 241 | __self.res.end(); 242 | } 243 | return false; 244 | } 245 | 246 | parseUrlParams() { 247 | const _url = url.parse(this.req.url); 248 | this.UrlInfo = _url; 249 | const { query } = _url; 250 | this.token = this.req.headers.token; 251 | this.QueryParams = querystring.parse(query); 252 | } 253 | 254 | __FindMethod(PathInfo, isSendMsg) { 255 | const { pathname } = this.UrlInfo; 256 | const pathList = pathname.split('/'); 257 | pathList.shift(); 258 | if (pathList.length === 1) { 259 | if (isSendMsg) { 260 | this.res.Send_404({ status: 404, msg: pathname + '接口没有找到' }); 261 | } 262 | return null; 263 | } 264 | const __last = pathList.pop(); 265 | let __CallApi = this.ApiInfo[pathList[0]]; 266 | if (!__CallApi) { 267 | return null; 268 | } 269 | let __ApiIsExist = true; 270 | for (let i = 1; i < pathList.length; i++) { 271 | __CallApi = __CallApi[pathList[i]]; 272 | if (!__CallApi) { 273 | __ApiIsExist = false; 274 | break; 275 | } 276 | } 277 | if (!__ApiIsExist) { 278 | if (isSendMsg) { 279 | this.res.Send_404({ status: 404, msg: pathname + '接口没有找到' }); 280 | } 281 | return null; 282 | } 283 | const Controller = __CallApi; 284 | __CallApi = __CallApi[this.Method + '_' + __last] 285 | if (!__CallApi) { 286 | if (isSendMsg) { 287 | this.res.Send_404({ status: 404, msg: pathname + '接口没有找到' }); 288 | } 289 | return null; 290 | } 291 | 292 | return { func: __CallApi, ctrl: Controller }; 293 | } 294 | } 295 | 296 | console.log('---process.env.PORT-', process.env.APIPORT); 297 | 298 | const start = new Server(); 299 | start.CreateServer(process.env.APIPORT); 300 | -------------------------------------------------------------------------------- /server/lib/Log.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by liaohb on 15-10-12 下午4:04. 3 | * File name By lhb_log.js 4 | */ 5 | 6 | 7 | class XTN_Log { 8 | static Print(args) { 9 | // var len = arguments.length; 10 | // var printContent = "" 11 | // if (len > 1) { 12 | // for (var i = 0; i < len; i++) { 13 | // printContent += arguments[i] + " "; 14 | // } 15 | // } 16 | // else { 17 | // printContent = arg; 18 | // } 19 | // console.log(new Date().Format("yyyy-MM-dd hh:mm:ss.S") + "------------[BEGIN]------------"); 20 | // try { 21 | // throw new Error(); 22 | // } catch (e) { 23 | // var loc = e.stack.replace(/Error\n/).split(/\n/)[1].replace(/^\s+|\s+$/, ""); 24 | // console.log(loc); 25 | // } 26 | console.log(...arguments); 27 | // console.log(new Date().Format("yyyy-MM-dd hh:mm:ss.S") + "------------[END]--------------"); 28 | } 29 | 30 | static GetInfo(args) { 31 | 32 | } 33 | } 34 | 35 | module.exports = XTN_Log; -------------------------------------------------------------------------------- /server/lib/Utility.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by liaohb on 15-10-12 上午10:09. 3 | * File name By CommonMethods.js 4 | */ 5 | var util = require("util"); 6 | const crypto = require('crypto'); 7 | const buffer = require("buffer").Buffer; 8 | const _LogInfo = require("./Log"); 9 | 10 | const _encrypt_key = "xiaotuni@liaohaibing!@#$%^&*()"; 11 | 12 | /** 13 | * 14 | * @type {{ToMD5: Function, ToSHA1: Function, ToEncryptAES: Function, ToDecryptAES: Function, IsArray: Function, IsString: Function, IsDate: Function, IsFunction: Function, IsObject: Function, IsNumber: Function}} 15 | */ 16 | class Utility { 17 | constructor() { 18 | this.Log = _LogInfo; 19 | } 20 | 21 | static format(format) { 22 | const args = Array.prototype.slice.call(arguments, 1); 23 | return format.replace(/{(\d+)}/g, (match, number) => { 24 | return typeof args[number] !== 'undefined' 25 | ? args[number] : match; 26 | }); 27 | } 28 | 29 | /** 30 | * 去空格 31 | * @param value 32 | * @returns {*} 33 | */ 34 | static $trim(value) { 35 | if (typeof value !== 'undefined') { 36 | return value.replace(/(^\s*)|(\s*$)/g, ''); 37 | } 38 | return ''; 39 | } 40 | 41 | /** 42 | * 获取当前时间 43 | * @returns {*} 44 | * @constructor 45 | */ 46 | static GetCurrentDate() { 47 | return new Date().Format("yyyy-MM-dd hh:mm:ss.S"); 48 | } 49 | 50 | /** 51 | * md5 加密 52 | * @param data 要加密的数据 53 | * @returns {*} 返回加密后的内容 54 | * @constructor 55 | */ 56 | static ToMD5(data) { 57 | var buf = new buffer(data); 58 | var str = buf.toString("binary"); 59 | return crypto.createHash("md5").update(str).digest("hex"); 60 | } 61 | 62 | /** 63 | * sah1 加密 64 | * @param data 要加密的数据 65 | * @returns {*} 返回加密后的内容 66 | * @constructor 67 | */ 68 | static ToSHA1(data) { 69 | var buff = new buffer(data); 70 | var str = buff.toString('binary'); 71 | return crypto.createHash("sha1").update(str).digest("hex"); 72 | } 73 | 74 | //http://blog.shiqichan.com/encrypt-and-decrypt-string-with-aes/ 75 | /** 76 | * 加密函数 77 | * @param data 要加密的数据 78 | * @returns {*} 返回加密后的内容 79 | * @constructor 80 | */ 81 | static ToEncryptAES(data) { 82 | var cipher = crypto.createCipher('aes-256-cbc', _encrypt_key); 83 | var text = data; 84 | var crypted = cipher.update(text, 'utf8', 'hex'); 85 | crypted += cipher.final('hex'); 86 | return crypted; 87 | } 88 | 89 | /** 90 | * 解密函数 91 | * @param data 要解密的数据 92 | * @returns {*} 返回解密后的数据 93 | * @constructor 94 | */ 95 | static ToDecryptAES(data) { 96 | var decipher = crypto.createDecipher('aes-256-cbc', _encrypt_key); 97 | var dec = decipher.update(data, 'hex', 'utf8'); 98 | dec += decipher.final('utf8'); 99 | return dec; 100 | } 101 | 102 | /** 103 | * 判断是否为数组类型 104 | * @param data 105 | * @returns {boolean} 106 | * @constructor 107 | */ 108 | static IsArray(data) { 109 | return (typeof data == 'array') && data.constructor == Array; 110 | } 111 | 112 | /** 113 | * 判断是否为字符串类型 114 | * @param data 115 | * @returns {boolean} 116 | * @constructor 117 | */ 118 | static IsString(data) { 119 | return (typeof data == 'string') && data.constructor == String; 120 | } 121 | 122 | /** 123 | * 判断是否为日期类型 124 | * @param data 125 | * @returns {boolean} 126 | */ 127 | static IsDate(data) { 128 | return (typeof data == 'date') && data.constructor == Date; 129 | } 130 | 131 | /** 132 | * 判断是否为函数 133 | * @param data 134 | * @returns {boolean} 135 | * @constructor 136 | */ 137 | static IsFunction(data) { 138 | return (typeof data == 'function') && data.constructor == Function; 139 | } 140 | 141 | /** 142 | * 判断是否为对象 143 | * @param data 144 | * @returns {boolean} 145 | * @constructor 146 | */ 147 | static IsObject(data) { 148 | return (typeof data == 'object') && data.constructor == Object; 149 | } 150 | /** 151 | * 判断是否是 Number 152 | * @param data 153 | * @returns {boolean} 154 | * @constructor 155 | */ 156 | static IsNumber(data) { 157 | return (typeof data == 'number') && data.constructor == Number; 158 | } 159 | 160 | /** 161 | * 判断是否是 NaN 类型 162 | * @param data 163 | * @returns {boolean} 164 | * @constructor 165 | */ 166 | static IsNaN(data) { 167 | return Number.isNaN(data); 168 | } 169 | 170 | /** 171 | * 用 util.inspect 格式化对象, 172 | * 173 | * @static 174 | * @param {any} args 175 | * @returns 176 | * @memberof Utility 177 | */ 178 | static ParseObject(args) { 179 | return util.inspect(object, true, 12, true); 180 | } 181 | 182 | } 183 | Utility.ConstItem = { 184 | CaptchaInfo: { 185 | 186 | } 187 | } 188 | 189 | module.exports = Utility; -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | 6 | 7 |
8 |
9 |
10 |
11 | 12 |
13 |
-------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/app.component.scss -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async(() => { 7 | TestBed.configureTestingModule({ 8 | declarations: [ 9 | AppComponent 10 | ], 11 | }).compileComponents(); 12 | })); 13 | 14 | it('should create the app', async(() => { 15 | const fixture = TestBed.createComponent(AppComponent); 16 | const app = fixture.debugElement.componentInstance; 17 | expect(app).toBeTruthy(); 18 | })); 19 | 20 | it(`should have as title 'app works!'`, async(() => { 21 | const fixture = TestBed.createComponent(AppComponent); 22 | const app = fixture.debugElement.componentInstance; 23 | expect(app.title).toEqual('app works!'); 24 | })); 25 | 26 | it('should render title in a h1 tag', async(() => { 27 | const fixture = TestBed.createComponent(AppComponent); 28 | fixture.detectChanges(); 29 | const compiled = fixture.debugElement.nativeElement; 30 | expect(compiled.querySelector('h1').textContent).toContain('app works!'); 31 | })); 32 | }); 33 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Title } from '@angular/platform-browser'; 3 | import { Router, RoutesRecognized, NavigationEnd, ActivatedRoute } from '@angular/router'; 4 | import { Location } from '@angular/common'; 5 | import { Utility } from './containers/Core'; 6 | import { ServiceHelper } from './service/index' 7 | import { EventEmitter } from 'events'; 8 | 9 | 10 | @Component({ 11 | selector: 'app-root', 12 | templateUrl: './app.component.html', 13 | styleUrls: ['./app.component.scss'], 14 | providers: [ServiceHelper] 15 | }) 16 | export class AppComponent { 17 | __Title111 = 'app works!'; 18 | private __Location: Location; 19 | public ActionSheetInfo: any; 20 | public ActionSheetList: Array = new Array(); 21 | public DialogList: Array = new Array(); 22 | 23 | constructor(private router: Router, 24 | private location: Location, 25 | private activatedRoute: ActivatedRoute, 26 | private titleService: Title, 27 | private sHelper: ServiceHelper) { 28 | this.__Location = location; 29 | this.__RouterListen(router); 30 | this.__ListenEmit(this); 31 | } 32 | 33 | __RouterListen(router: Router): void { 34 | Utility.$SetContent(Utility.$ConstItem.Route, router, false); 35 | Utility.$SetContent(Utility.$ConstItem.BrowerTitle, this.titleService, false); 36 | Utility.$SetContent(Utility.$ConstItem.Location, this.__Location, false); 37 | Utility.$SetContent(Utility.$ConstItem.Event, new EventEmitter(), false); 38 | 39 | const _FindFirstChild = (parent) => { 40 | // 41 | const { firstChild } = parent; 42 | if (firstChild) { 43 | return _FindFirstChild(firstChild); 44 | } 45 | return parent; 46 | }; 47 | const __self = this; 48 | router.events.subscribe((obj: any) => { 49 | if (obj instanceof RoutesRecognized) { 50 | const state = obj.state; 51 | const root = state.root; 52 | const queryParams = root.queryParams; 53 | // __self.sHelper.Common.CurrentRouterPathInfo = { queryParams, Url: obj.url }; 54 | Utility.$SetContent(Utility.$ConstItem.UrlPathInfo, { Params: queryParams, Url: obj.url }, false); 55 | const firstChild = _FindFirstChild(root.firstChild); 56 | const routeConfig = firstChild.routeConfig; 57 | const { path, data } = routeConfig; 58 | const { title } = data || { title: '空' }; 59 | this.titleService.setTitle(title); 60 | __self.__Title111 = title; 61 | } 62 | }); 63 | 64 | } 65 | 66 | __GoBack() { 67 | Utility.$GoBack(); 68 | } 69 | 70 | __ListenEmit(_this) { 71 | const { ShowModel, HttpStatus } = Utility.$ConstItem.Events; 72 | Utility.$On(HttpStatus[400], (args) => { 73 | Utility.$Emit(ShowModel.onActionSheet, args); 74 | }); 75 | Utility.$On(HttpStatus[401], (args) => { 76 | const _a = _this; 77 | const ToPage = { Url: Utility.$ConstItem.UrlItem.ManagerLogin, Params: { IsGoBack: 1 } }; 78 | Utility.$Emit(ShowModel.onActionSheet, Object.assign(args, { ToPage })); 79 | }); 80 | Utility.$On(HttpStatus[404], (args) => { 81 | Utility.$Emit(ShowModel.onActionSheet, args); 82 | }); 83 | Utility.$On(HttpStatus[500], (args) => { 84 | Utility.$Emit(ShowModel.onActionSheet, args); 85 | }); 86 | Utility.$On(ShowModel.onActionSheet, (args) => { 87 | _this.ActionSheetList.push(args); 88 | }); 89 | Utility.$On(ShowModel.onActionSheetHide, (index) => { 90 | if (index >= 0) { 91 | _this.ActionSheetList[index].IsClose = true; 92 | } 93 | setTimeout(() => { 94 | if (index >= 0) { 95 | _this.ActionSheetList.splice(index, 1); 96 | } else { 97 | _this.ActionSheetList.pop(); 98 | } 99 | }, 100); 100 | }); 101 | 102 | Utility.$On(ShowModel.onDialog, (args) => { 103 | _this.DialogList.push(args); 104 | }); 105 | Utility.$On(ShowModel.onDialogHide, (index) => { 106 | if (index >= 0) { 107 | _this.DialogList[index].IsClose = true; 108 | } 109 | setTimeout(() => { 110 | if (index >= 0) { 111 | _this.DialogList.splice(index, 1); 112 | } else { 113 | _this.DialogList.pop(); 114 | } 115 | }, 200); 116 | }); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 3 | import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 4 | import { FormsModule } from '@angular/forms'; 5 | import { HttpModule } from '@angular/http'; 6 | 7 | import { AppRouting } from './app.router'; 8 | import { CommonComponent, PageComponentList } from './containers/Index'; 9 | import { ManagerPageComponentList } from './manage/Index'; 10 | import { ManagerApiPageComponentList } from './manageapi/Index'; 11 | 12 | import { AppComponent } from './app.component'; 13 | const Routers = AppRouting.Router(); 14 | 15 | @NgModule({ 16 | declarations: [AppComponent, PageComponentList, ManagerPageComponentList, ManagerApiPageComponentList, CommonComponent], 17 | imports: [BrowserAnimationsModule, BrowserModule, FormsModule, HttpModule, Routers], 18 | providers: [], 19 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 20 | entryComponents: [CommonComponent], 21 | bootstrap: [AppComponent] 22 | }) 23 | export class AppModule { } 24 | -------------------------------------------------------------------------------- /src/app/app.router.ts: -------------------------------------------------------------------------------- 1 | import { RouterModule } from '@angular/router'; 2 | import { RouterComponent } from './containers/Index'; 3 | import { ManagerRouter } from './manage/Index'; 4 | import { ManagerApiRouter } from './manageapi/Index'; 5 | export const AppRouting = { 6 | Router() { 7 | const { BaiduMap, BaiduMyJoinPlace, BaiduMyPlaceList, Product, Members, MyComponent, NotFound, Home } = RouterComponent; 8 | const { Login, UserList, Register, Dashboard, 9 | Address, Place, PlaceList, Contacts } = ManagerRouter; 10 | const { ApiList } = ManagerApiRouter; 11 | const routes = [ 12 | { path: '', redirectTo: 'home', pathMatch: 'full', data: { title: '首页' } }, 13 | { path: 'home', component: Home, data: { title: '首页' } }, 14 | { path: 'member', component: Members, data: { title: '成员列表' } }, 15 | { path: 'product', component: Product, data: { title: '产品信息' } }, 16 | { path: 'mycomponent', component: MyComponent, data: { title: '我的组件' } }, 17 | { 18 | path: 'baidumap', data: { title: '地图' }, 19 | children: [ 20 | { path: '', component: BaiduMap, data: { title: '地图' } }, 21 | { path: 'myplace', component: BaiduMyPlaceList, data: { title: '我发起的活动' } }, 22 | { path: 'myjoinplace', component: BaiduMyJoinPlace, data: { title: '我要加入' } }, 23 | ] 24 | }, 25 | { 26 | path: 'manager', data: { title: '用户登录' }, 27 | children: [ 28 | { path: 'register', component: Register, data: { title: '用户注册' } }, 29 | { path: 'login', component: Login, data: { title: '用户登录' } }, 30 | { path: 'userlist', component: UserList, data: { title: '用户列表' } }, 31 | { path: 'dashboard', component: Dashboard, data: { title: '控制面板' } }, 32 | { path: 'address', component: Address, data: { title: '我的地址' } }, 33 | { 34 | path: 'place', data: { title: '目的地' }, 35 | children: [ 36 | { path: '', component: Place, data: { title: '目的地1' } }, 37 | { path: 'list', component: PlaceList, data: { title: '目的地列表' } }, 38 | ] 39 | }, 40 | { path: 'contacts', component: Contacts, data: { title: '联系人' } }, 41 | ] 42 | }, 43 | { 44 | path: 'api', data: { title: '后台API管理' }, 45 | children: [ 46 | { path: 'list', component: ApiList, data: { title: 'Api列表' } }, 47 | ] 48 | }, 49 | 50 | { path: '**', component: NotFound, data: { title: '404页面未找到' } } 51 | ]; 52 | return RouterModule.forRoot(routes, { useHash: !true }); 53 | }, 54 | } 55 | -------------------------------------------------------------------------------- /src/app/components/ComponentTools.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/components/ComponentTools.ts -------------------------------------------------------------------------------- /src/app/components/Confirm/Confirm.html: -------------------------------------------------------------------------------- 1 |
2 |
{{_Title}}
3 |
4 |
5 | 6 |
7 |
-------------------------------------------------------------------------------- /src/app/components/Confirm/Confirm.scss: -------------------------------------------------------------------------------- 1 | .confirmCss { 2 | position: relative; 3 | margin-top: 5px; 4 | 5 | .title { 6 | padding: 5px 20px; 7 | font-size: 16px; 8 | color: #222; 9 | text-align: center; 10 | } 11 | .line { 12 | border-top: 1px solid #e0e0e0; 13 | width: 100%; 14 | margin-bottom: 5px; 15 | } 16 | .input { 17 | padding: 5px; 18 | margin: 5px; 19 | 20 | input { 21 | font-size: 16px; 22 | padding: 5px; 23 | border-radius: 5px; 24 | outline-style: none; 25 | border: 1px solid #bfd2f5; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/app/components/Confirm/Confirm.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; 2 | import { Utility, OnDialog } from '../Core'; 3 | 4 | @Component({ 5 | moduleId: module.id, 6 | selector: 'xtn-confirm', 7 | templateUrl: 'Confirm.html', 8 | styleUrls: ['./Confirm.scss'] 9 | }) 10 | export class XtnConfirm implements OnInit, OnDialog { 11 | 12 | @Input('Title') _Title: string; //标题 13 | @Output('onConfirm') _onConfirm: EventEmitter = new EventEmitter(); 14 | InputValue: string; 15 | 16 | constructor() { } 17 | 18 | ngOnInit() { 19 | 20 | } 21 | 22 | onDialogConfirm(dialog): void { 23 | if (this._onConfirm) { 24 | this._onConfirm.emit({ dialog, args: this.InputValue }); 25 | } 26 | } 27 | 28 | onDialogCancel(dialog): void { 29 | dialog.onClose(); 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /src/app/components/Core.ts: -------------------------------------------------------------------------------- 1 | export { Utility } from '../Common/Utility'; 2 | 3 | export interface OnDialog { 4 | onDialogConfirm(dialog: any): void; 5 | onDialogCancel(dialog: any): void; 6 | } 7 | // export interface onDialogCancel { onCancel(): void; } -------------------------------------------------------------------------------- /src/app/components/Index.ts: -------------------------------------------------------------------------------- 1 | import { __XtnDefRefComponent } from './__defref/defref'; 2 | import { NavbarComponent } from './navbar/navbar.component' 3 | import { XtnApiItem } from './apiitem/apiitem' 4 | import { RuleItem } from './rule/ruleitem' 5 | import { RuleInfo } from './rule/RuleInfo' 6 | import { XtnModel } from './model/Core'; 7 | import { MapComponent } from './Map/Index'; 8 | import { XtnScroll } from './Scroll/Scroll'; 9 | import { XtnConfirm } from './Confirm/Confirm'; 10 | 11 | export const CommonComponent = [ 12 | NavbarComponent, __XtnDefRefComponent, RuleItem, RuleInfo, XtnApiItem, XtnModel, 13 | MapComponent, XtnScroll, XtnConfirm 14 | ]; 15 | -------------------------------------------------------------------------------- /src/app/components/Map/Core.ts: -------------------------------------------------------------------------------- 1 | import { XtnMapPlaceItem } from './PlaceItem/PlaceItem'; 2 | 3 | 4 | export const MapComponent = [XtnMapPlaceItem]; -------------------------------------------------------------------------------- /src/app/components/Map/Index.ts: -------------------------------------------------------------------------------- 1 | import { XtnMapPlaceItem } from './PlaceItem/PlaceItem'; 2 | import { XtnBaiduMapMarker } from './marker/marker'; 3 | 4 | 5 | export const MapComponent = [XtnMapPlaceItem, XtnBaiduMapMarker]; -------------------------------------------------------------------------------- /src/app/components/Map/PlaceItem/PlaceItem.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 聚会名称 4 |
5 |
6 | 7 |
8 |
9 | 聚会地点 10 |
11 |
12 | 13 |
14 |
15 | 描述 16 |
17 |
18 | 19 |
20 |
21 |
开始时间:
22 | 23 |
24 |
25 |
结束时间:
26 | 27 |
28 |
29 | 30 |
31 |
-------------------------------------------------------------------------------- /src/app/components/Map/PlaceItem/PlaceItem.scss: -------------------------------------------------------------------------------- 1 | .placeItem { 2 | position: relative; 3 | width: 80vw; // calc(100vw - 100px); 4 | padding: 5px 15px 5px 10px; 5 | .title { 6 | padding: 10px 5px; 7 | } 8 | 9 | .address { 10 | padding: 5px; 11 | position: relative; 12 | 13 | input { 14 | position: relative; 15 | width: 100%; 16 | padding: 5px 0; 17 | border: 1px solid #c4c4ea; 18 | border-radius: 5px; 19 | padding-left: 5px; 20 | } 21 | } 22 | 23 | .bewrite { 24 | padding: 5px; 25 | position: relative; 26 | 27 | textarea { 28 | position: relative; 29 | width: 100%; 30 | padding: 5px 0; 31 | border: 1px solid #c4c4ea; 32 | border-radius: 5px; 33 | height: 50px; 34 | } 35 | } 36 | 37 | .date { 38 | position: relative; 39 | display: flex; 40 | align-items: center; 41 | 42 | input { 43 | flex: 1; 44 | padding: 2px 0; 45 | border: 1px solid #c4c4ea; 46 | border-radius: 5px; 47 | padding-left: 5px; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/app/components/Map/PlaceItem/PlaceItem.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, Input, AfterContentInit, EventEmitter } from '@angular/core'; 2 | import { Utility, OnDialog } from '../../Core'; 3 | 4 | @Component({ 5 | selector: 'xtn-map-place-item', 6 | templateUrl: './PlaceItem.html', 7 | styleUrls: ['./PlaceItem.scss'] 8 | }) 9 | export class XtnMapPlaceItem implements OnInit, OnDialog { 10 | 11 | @Input('Place') place: any; 12 | @Input() Params: any; 13 | @Output('onSave') _onSave: EventEmitter = new EventEmitter(); 14 | @Output('onDelete') _onDelete: EventEmitter = new EventEmitter(); 15 | @Output('onModify') _onModify: EventEmitter = new EventEmitter(); 16 | 17 | constructor() { 18 | 19 | } 20 | 21 | ngOnInit() { 22 | console.log('placeitem---', this.place); 23 | } 24 | 25 | onClickBtn(type) { 26 | switch (type) { 27 | case 1: 28 | this._onSave.emit({ type: 'save', value: type, place: this.place }); 29 | break; 30 | case 2: 31 | this._onDelete.emit({ type: 'delete', value: type, place: this.place }); 32 | break; 33 | case 3: 34 | this._onModify.emit({ type: 'modify', value: type, place: this.place }); 35 | break; 36 | } 37 | } 38 | 39 | 40 | onDialogConfirm(dialog) { 41 | if (this._onSave) { 42 | this._onSave.emit({ dialog, args: this.place }); 43 | } else { 44 | dialog.onClose(); 45 | } 46 | } 47 | 48 | onDialogCancel(dialog) { 49 | dialog.onClose(); 50 | } 51 | 52 | onBtnClickModify() { 53 | if (this._onModify) { 54 | this._onModify.emit('这是点击事件,调用的是修改事件'); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/app/components/Map/marker/marker.html: -------------------------------------------------------------------------------- 1 | aaaaa -------------------------------------------------------------------------------- /src/app/components/Map/marker/marker.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/components/Map/marker/marker.scss -------------------------------------------------------------------------------- /src/app/components/Map/marker/marker.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input, Output, OnChanges, AfterContentInit, EventEmitter } from '@angular/core'; 2 | import { Utility } from '../../Core'; 3 | 4 | @Component({ 5 | selector: 'xtn-baidu-map-marker', 6 | templateUrl: 'marker.html', 7 | styleUrls: ['marker.scss'] 8 | }) 9 | export class XtnBaiduMapMarker implements OnInit, OnChanges { 10 | 11 | @Input('EnableDragging') enableDragging: boolean; 12 | @Input('BMap') BMap: any; 13 | @Input('Map') __Map: any; 14 | @Input('Position') __CurrentPosition: any; 15 | @Output('onUpdatePosition') onUpdatePosition: EventEmitter = new EventEmitter(); 16 | __Marker: any; 17 | 18 | BaiduAnimation: any = { BMAP_ANIMATION_BOUNCE: 2, BMAP_ANIMATION_DROP: 1 }; 19 | 20 | constructor() { 21 | } 22 | 23 | ngOnInit() { 24 | } 25 | 26 | ngOnChanges(): void { 27 | const { point, address } = this.__CurrentPosition; 28 | console.log('marker-->', address); 29 | // const { BMAP_ANIMATION_BOUNCE } = window 30 | if (this.__Marker) { 31 | this.__Map.removeOverlay(this.__Marker); 32 | // this.__Marker.setPosition(this.__CurrentPosition.point); 33 | } 34 | this.__Marker = null; 35 | this.AddMarker(this.__CurrentPosition); 36 | } 37 | 38 | AddMarker(position) { 39 | if (!this.BMap || !position) { 40 | return; 41 | } 42 | const { point } = position; 43 | const self = this; 44 | const { onUpdatePosition } = this; 45 | 46 | const myIcon = new this.BMap.Icon("/assets/img/person-icon.png", 47 | new this.BMap.Size(48, 48), { 48 | // 指定定位位置。 49 | // 当标注显示在地图上时,其所指向的地理位置距离图标左上 50 | // 角各偏移10像素和25像素。您可以看到在本例中该位置即是 51 | // 图标中央下端的尖角位置。 52 | offset: new this.BMap.Size(48, 48), 53 | // 设置图片偏移。 54 | // 当您需要从一幅较大的图片中截取某部分作为标注图标时,您 55 | // 需要指定大图的偏移位置,此做法与css sprites技术类似。 56 | imageOffset: new this.BMap.Size(0, 0) // 设置图片偏移 57 | }); 58 | // 创建标注对象并添加到地图 59 | const marker = new this.BMap.Marker(point, { icon: myIcon }); 60 | const { BMAP_ANIMATION_BOUNCE, BMAP_ANIMATION_DROP } = window 61 | this.__Map.addOverlay(marker); 62 | marker.setAnimation(BMAP_ANIMATION_BOUNCE); 63 | setTimeout(() => { 64 | marker.setAnimation(null); 65 | }, 2000); 66 | 67 | // 点击图标事件 68 | marker.addEventListener("click", function (e) { 69 | console.log('点击图标啦', e); 70 | }); 71 | 72 | // 让图标可以进行拖拽。 73 | if (!!this.enableDragging) { 74 | marker.enableDragging(); 75 | marker.addEventListener("dragend", function (e) { 76 | console.log("当前位置:" + e.point.lng + ", " + e.point.lat); 77 | if (onUpdatePosition) { 78 | onUpdatePosition.emit(e); 79 | } 80 | }) 81 | } 82 | this.__Marker = marker; 83 | } 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/app/components/Scroll/Scroll.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
{{Info.TitleTop}}
4 |
5 | 6 |
7 |
{{Info.TitleBottom}}
8 |
9 | 10 |
-------------------------------------------------------------------------------- /src/app/components/Scroll/Scroll.scss: -------------------------------------------------------------------------------- 1 | .scrollCss { 2 | position: relative; 3 | // border: 1px solid; 4 | padding: 10px 5px; 5 | 6 | .top { 7 | position: relative; 8 | text-align: center; 9 | display: none; 10 | transition: .2s; 11 | overflow: hidden; 12 | 13 | .title { 14 | position: absolute; 15 | width: 100%; 16 | bottom: 10px; 17 | } 18 | } 19 | 20 | .bottom { 21 | position: relative; 22 | overflow: hidden; 23 | transition: .2s; 24 | text-align: center; 25 | display: none; 26 | .title { 27 | width: 100%; 28 | display: -webkit-box; 29 | -webkit-box-align: center; 30 | -webkit-box-pack: center; 31 | height: 100%; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app/components/Scroll/Scroll.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, OnInit, Input, Output, OnChanges, AfterContentInit, EventEmitter, ElementRef, ViewChild, 3 | trigger, state, style, transition, animate 4 | } from '@angular/core'; 5 | import { Utility } from '../Core'; 6 | 7 | @Component({ 8 | selector: 'xtn-scroll', 9 | templateUrl: 'Scroll.html', 10 | styleUrls: ['Scroll.scss'] 11 | }) 12 | export class XtnScroll implements OnInit, OnChanges { 13 | 14 | Info: any; 15 | @Input('Percentage') _Percentage: number; 16 | @Input('IsRefreshFinish') _IsRefreshFinish: boolean; 17 | @Input('IsNextPageFinish') _IsNextPageFinish: boolean; 18 | @Input('IsSlideLeftFinish') _IsSlideLeftFinish: boolean; 19 | @Input('IsSlideRightFinish') _IsSlideRightFinish: boolean; 20 | @Output('onRefresh') _onRefresh: EventEmitter = new EventEmitter(); 21 | @Output('onNextPage') _onNextPage: EventEmitter = new EventEmitter(); 22 | @Output('onSlideLeft') _onSlideLeft: EventEmitter = new EventEmitter(); 23 | @Output('onSlideRight') _onSlideRight: EventEmitter = new EventEmitter(); 24 | 25 | @ViewChild('divTop') divTop: ElementRef; 26 | @ViewChild('divContent') divContent: ElementRef; 27 | @ViewChild('divBottom') divBottom: ElementRef; 28 | 29 | Top50Name: any; 30 | 31 | constructor() { 32 | this.Info = { 33 | Start: { X: 0, Y: 0 }, 34 | Move: { X: 0, Y: 0 }, 35 | End: { X: 0, Y: 0 }, 36 | TitleTop: '下拉刷新', 37 | TitleBottom: '上拉获取下面数据', 38 | }; 39 | } 40 | 41 | ngOnInit() { 42 | } 43 | 44 | ngOnChanges(): void { 45 | if (!!this._IsRefreshFinish) { 46 | const { Info, divTop } = this; 47 | Info.TitleTop = '更新完成...'; 48 | setTimeout(function () { 49 | divTop.nativeElement.style.height = '0px'; 50 | setTimeout(() => { 51 | divTop.nativeElement.style.display = 'none'; 52 | Info.TitleTop = '下拉刷新...'; 53 | delete Info.IsTitleTop; 54 | }, 500); 55 | }, 500); 56 | } 57 | if (!!this._IsNextPageFinish) { 58 | const { Info, divBottom } = this; 59 | Info.TitleBottom = '加载完成...'; 60 | setTimeout(() => { 61 | divBottom.nativeElement.style.height = '0px'; 62 | setTimeout(() => { 63 | divBottom.nativeElement.style.display = 'none'; 64 | Info.TitleTop = '下拉刷新...'; 65 | delete Info.IsTitleTop; 66 | }, 500); 67 | }, 500); 68 | } 69 | } 70 | 71 | __UpdateLocation(type, event) { 72 | const { changedTouches } = event; 73 | const { clientX, clientY } = changedTouches[0]; 74 | this.Info[type].X = clientX; 75 | this.Info[type].Y = clientY; 76 | } 77 | 78 | OnTouchStart(event) { 79 | this.__UpdateLocation('Start', event); 80 | } 81 | 82 | OnTouchMove(event) { 83 | this.__UpdateLocation('Move', event); 84 | this.__JudgeRefreshOrNextPage(); 85 | } 86 | 87 | OnTouchEnd(event) { 88 | this.__UpdateLocation('End', event); 89 | this.__RefreshOrNextPageEnd(); 90 | const { Start, End, divTop, divBottom } = this.Info; 91 | 92 | const xes = End.X - Start.X; 93 | const yes = End.Y - Start.Y; 94 | 95 | const absXes = Math.abs(xes); 96 | const absYes = Math.abs(yes); 97 | 98 | if (absXes < 10 && absYes < 20) { 99 | this.__Reset(); 100 | return; 101 | } 102 | if (xes > 0) { 103 | // 右 104 | if (yes > 0) { 105 | // 向下 106 | // 判断主向 107 | if (absXes > absYes) { 108 | // 向右。 109 | this.SlideRight(); 110 | } else { 111 | // 向下。 112 | this.SlideRefresh(); 113 | } 114 | } else { 115 | // 向上 116 | if (absXes > absYes) { 117 | // 向右。 118 | this.SlideRight(); 119 | } else { 120 | // 向上。 121 | this.SlideNextPage(); 122 | } 123 | } 124 | } else { 125 | // 左边 126 | if (yes > 0) { 127 | // 向下 128 | if (absXes > absYes) { 129 | // 向左。 130 | this.SlideLeft(); 131 | } else { 132 | // 向下。 133 | this.SlideRefresh(); 134 | } 135 | } else { 136 | // 向上 137 | if (absXes > absYes) { 138 | this.SlideLeft(); 139 | } else { 140 | this.SlideNextPage(); 141 | } 142 | } 143 | } 144 | } 145 | 146 | __Reset() { 147 | const { divTop, divBottom, Info } = this; 148 | divTop.nativeElement.style.height = '0px'; 149 | divBottom.nativeElement.style.height = '0px'; 150 | divTop.nativeElement.style.display = 'none'; 151 | divBottom.nativeElement.style.display = 'none'; 152 | Info.TitleTop = '下拉刷新'; 153 | Info.TitleBottom = '上拉获取下面数据'; 154 | } 155 | 156 | SlideLeft() { 157 | const { _onSlideLeft } = this; 158 | if (_onSlideLeft) { 159 | _onSlideLeft.emit(); 160 | } 161 | } 162 | 163 | SlideRight() { 164 | const { _onSlideRight } = this; 165 | if (!_onSlideRight) { 166 | return; 167 | } 168 | _onSlideRight.emit(); 169 | } 170 | 171 | SlideNextPage() { 172 | const { _onNextPage, _Percentage, Info, divBottom } = this; 173 | if (!_onNextPage) { 174 | return; 175 | } 176 | const __ctrl = document.body.children[0].children[1]; 177 | const { scrollTop, scrollHeight } = __ctrl; 178 | 179 | const __bodyScrollTop = scrollTop; 180 | const __bodyScrollHeight = scrollHeight; 181 | const __differValue = ((__bodyScrollHeight - __bodyScrollTop - screen.height) / __bodyScrollHeight) * 100; 182 | if (__differValue > (_Percentage < 3 ? 3 : _Percentage)) { 183 | this.__Reset(); 184 | return; 185 | } 186 | _onNextPage.emit(); 187 | 188 | if (!!Info.IsTitleBottom) { 189 | Info.TitleBottom = '正在获取数据...'; 190 | divBottom.nativeElement.style.height = '30px'; 191 | } else { 192 | divBottom.nativeElement.style.height = '0px'; 193 | } 194 | } 195 | 196 | SlideRefresh() { 197 | const { _onRefresh } = this; 198 | if (!_onRefresh) { 199 | return; 200 | } 201 | const __ctrl = document.body.children[0].children[1]; 202 | const { scrollTop } = __ctrl; 203 | if (scrollTop === 0) { 204 | _onRefresh.emit(); 205 | 206 | const { Info, divTop } = this; 207 | if (!!Info.IsTitleTop) { 208 | Info.TitleTop = '更新中...'; 209 | divTop.nativeElement.style.height = '30px'; 210 | } else { 211 | divTop.nativeElement.style.height = '0px'; 212 | } 213 | } else { 214 | this.__Reset(); 215 | } 216 | } 217 | 218 | __JudgeRefreshOrNextPage() { 219 | const { Start, Move, TitleTop } = this.Info; 220 | const xes = Move.X - Start.X; 221 | const yes = Move.Y - Start.Y; 222 | const absXes = Math.abs(xes); 223 | const absYes = Math.abs(yes); 224 | const { divTop, divBottom } = this; 225 | if (absXes > 20) { 226 | if (absYes < absXes) { 227 | return; 228 | } 229 | } 230 | if (yes > 0) { // Refresh 操作 231 | divTop.nativeElement.style.display = 'none'; 232 | if (yes > 20) { 233 | this.Info.TitleTop = '下拉刷新...'; 234 | divTop.nativeElement.style.display = 'inherit'; 235 | 236 | if (yes > 50) { 237 | this.Info.IsTitleTop = true; 238 | this.Info.TitleTop = '释放刷新数据...'; 239 | } 240 | if (yes < 120) { 241 | divTop.nativeElement.style.height = yes + 'px'; 242 | } 243 | } 244 | } else { 245 | divBottom.nativeElement.style.display = 'none'; 246 | if (absYes > 20) { 247 | this.Info.TitleBottom = '上拉加获取数据...'; 248 | divBottom.nativeElement.style.display = 'inherit'; 249 | 250 | if (absYes > 30) { 251 | this.Info.IsTitleBottom = true; 252 | this.Info.TitleBottom = '释放加载下一页数据...'; 253 | } 254 | if (absYes < 60) { 255 | divBottom.nativeElement.style.height = absYes + 'px'; 256 | } 257 | } 258 | } 259 | } 260 | 261 | __RefreshOrNextPageEnd() { 262 | 263 | 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /src/app/components/__defref/defref.html: -------------------------------------------------------------------------------- 1 |
2 | 18 | 19 |
20 |
21 |
{{item.Title}}
22 |
23 |
24 |
-------------------------------------------------------------------------------- /src/app/components/__defref/defref.scss: -------------------------------------------------------------------------------- 1 | .appCss { 2 | padding: 5px; 3 | 4 | .btnGoBack { 5 | margin: 5px; 6 | display: flex; 7 | 8 | & > div { 9 | padding: 5px 25px; 10 | border: 1px solid #f5f5f5; 11 | background: blue; 12 | color: #fff; 13 | border-radius: 5px; 14 | 15 | &:hover { 16 | background: #999; 17 | } 18 | } 19 | } 20 | 21 | .components { 22 | // padding: 5px; 23 | display: flex; 24 | flex-wrap: wrap; 25 | flex-direction: row; 26 | 27 | > div { 28 | margin-top: 5px; 29 | margin-right: 5px; 30 | 31 | > div { 32 | border: 1px solid #f5f5f5; 33 | padding: 5px 10px; 34 | border-radius: 5px; 35 | 36 | &:hover { 37 | border: 1px solid #999; 38 | background: #999; 39 | color: #fff; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/app/components/__defref/defref.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Utility } from '../Core'; 3 | 4 | @Component({ 5 | moduleId: module.id, 6 | selector: 'xtn-defref', 7 | templateUrl: 'defref.html', 8 | styleUrls: ['./defref.scss'] 9 | }) 10 | export class __XtnDefRefComponent implements OnInit { 11 | collection: Array = new Array(); 12 | constructor() { } 13 | 14 | ngOnInit() { 15 | const { UrlTitle } = Utility.$ConstItem; 16 | const __list = []; 17 | Object.keys(UrlTitle).forEach((key) => { 18 | __list.push(Object.assign({}, { key }, UrlTitle[key])); 19 | }); 20 | this.collection = __list; 21 | } 22 | 23 | __GoToPage(item) { 24 | Utility.$ToPage(item.key, {}); 25 | } 26 | } -------------------------------------------------------------------------------- /src/app/components/apiitem/apiitem.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 启用 6 |
7 |
8 | 9 | Token访问 10 |
11 |
12 | 请求方式: 13 | 16 |
17 | 接口: 18 | 19 |
20 |
21 |
保存
22 |
23 |
24 |
删除
25 |
26 |
27 |
28 |
29 | 30 |
31 | 32 |
-------------------------------------------------------------------------------- /src/app/components/apiitem/apiitem.scss: -------------------------------------------------------------------------------- 1 | .apiitemCss { 2 | border: 1px solid; 3 | 4 | >div { 5 | cursor: default; 6 | } 7 | 8 | .master { 9 | border-bottom: 1px solid #f0cccc; // padding: 10px; 10 | display: flex; 11 | align-items: center; 12 | 13 | .status { 14 | display: flex; 15 | align-items: center; 16 | border: 1px solid #f4f0f0; 17 | } 18 | 19 | .token { 20 | @extend .status; 21 | } 22 | 23 | .requestMethod { 24 | @extend .status; 25 | } 26 | 27 | .title { 28 | white-space: nowrap; 29 | overflow: hidden; 30 | padding: 5px; 31 | } 32 | 33 | input { 34 | padding: 5px; 35 | } 36 | 37 | input[type='text'] { 38 | flex: 1; 39 | } 40 | } 41 | .bewrite { 42 | display: flex; 43 | input { 44 | flex: 1; 45 | padding: 5px; 46 | } 47 | } 48 | 49 | >div:last-child { 50 | border-bottom: none; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/app/components/apiitem/apiitem.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnChanges, Output, Input, EventEmitter } from '@angular/core'; 2 | import { animate, state, style, transition, trigger } from '@angular/animations'; 3 | import { Utility } from '../Core'; 4 | @Component({ 5 | selector: 'xtn-api-item', 6 | templateUrl: './apiitem.html', 7 | styleUrls: ['./apiitem.scss'], 8 | animations: [trigger( 9 | 'openClose', 10 | [ 11 | state('collapsed, void', style({ position: 'relative', background: '#fff', height: '0px', color: 'maroon', borderColor: 'maroon', display: 'none' })), 12 | state('expanded', style({ position: 'relative', background: '#fff', height: '*', borderColor: 'green', color: 'green' })), 13 | // transition('collapsed <=> expanded', [animate(500, style({ background: '#fff', height: '*', color: 'blue' })), animate(100)]), 14 | transition('collapsed <=> expanded', [animate('100ms ease-out'), animate('100ms ease-out')]), 15 | ])] 16 | }) 17 | export class XtnApiItem implements OnInit, OnChanges { 18 | 19 | @Input('Source') ApiInfo: any; 20 | @Input('Index') Index: number; 21 | @Input('IsExpanded') IsExpanded: boolean; 22 | stateExpression: string = 'collapsed'; 23 | 24 | 25 | @Output() onDelete: EventEmitter = new EventEmitter(); 26 | @Output() onSave: EventEmitter = new EventEmitter(); 27 | 28 | public RuleInfo: any; 29 | 30 | public MethodCollection: Array = [ 31 | { key: 'get', title: 'get' }, 32 | { key: 'delete', title: 'delete' }, 33 | { key: 'post', title: 'post' }, 34 | { key: 'put', title: 'put' }, 35 | ]; 36 | constructor() { 37 | } 38 | ngOnChanges(): void { 39 | this.stateExpression = !!this.IsExpanded ? 'expanded' : 'collapsed'; 40 | } 41 | ngOnInit() { 42 | 43 | if (!this.ApiInfo) { 44 | this.ApiInfo = {}; 45 | } 46 | // if (!this.ApiInfo['IsTokenAccess'] ) { 47 | // this.ApiInfo.IsTokenAccess = 1; 48 | // } 49 | // if (!this.ApiInfo['Status']) { 50 | // this.ApiInfo.Status = 1; 51 | // } 52 | if (!this.ApiInfo.RuleInfo) { 53 | this.ApiInfo.RuleInfo = {}; 54 | } 55 | this.RuleInfo = this.ApiInfo.RuleInfo; 56 | } 57 | 58 | btnClickSave() { 59 | const { onSave, ApiInfo } = this; 60 | if (onSave) { 61 | onSave.emit(ApiInfo); 62 | } 63 | } 64 | 65 | btnClickDelete() { 66 | const { onDelete, ApiInfo } = this; 67 | if (onDelete) { 68 | onDelete.emit(ApiInfo); 69 | } 70 | } 71 | 72 | onClickCheckbox(type) { 73 | this.ApiInfo[type] = !this.ApiInfo[type]; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/app/components/model/ActionSheet/ActionSheet.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
标题
6 |
7 |
8 | {{Info.msg}} 9 |
10 |
11 |
12 |
-------------------------------------------------------------------------------- /src/app/components/model/ActionSheet/ActionSheet.scss: -------------------------------------------------------------------------------- 1 | .actionSheetCss { 2 | position: relative; 3 | justify-content: center; 4 | 5 | .bgInfo { 6 | position: fixed; 7 | top: 0; 8 | left: 0; 9 | width: 100%; 10 | height: 100%; 11 | background: rgba(0, 0, 0, 0.2); 12 | } 13 | 14 | .info { 15 | position: fixed; 16 | bottom: 0; 17 | width: 90%; 18 | left: 5%; 19 | justify-content: center; 20 | text-align: center; 21 | border: 1px solid #f0f0f0; 22 | border-top-left-radius: 10px; 23 | border-top-right-radius: 10px; 24 | border-bottom: none; 25 | background: #fff; 26 | 27 | .title { 28 | padding: 5px 10px; 29 | font-size: 20px; 30 | } 31 | 32 | .splitline { 33 | width: 100%; 34 | height: 1px; 35 | background: #cde8f7; 36 | } 37 | 38 | .content { 39 | padding: 5px 10px; 40 | font-size: 14px; 41 | white-space: normal; 42 | line-height: 1.78; 43 | } 44 | 45 | .btnList { 46 | margin-bottom: 5px; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/app/components/model/ActionSheet/ActionSheet.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, OnInit, Output, Input, AfterContentInit, AfterContentChecked, 3 | trigger, state, style, transition, animate 4 | } from '@angular/core'; 5 | import { Utility } from '../../Core'; 6 | 7 | @Component({ 8 | selector: 'xtn-mode-action-sheet', 9 | templateUrl: './ActionSheet.html', 10 | styleUrls: ['./ActionSheet.scss'], 11 | animations: [ 12 | trigger('TriggerState', [ 13 | state('up', style({ transform: 'translateY(0%)' })), 14 | state('down', style({ transform: 'translateY(100%)' })), 15 | transition('up => down', animate('100ms ease-in')), 16 | transition('down => up', animate('100ms ease-out')), 17 | ]) 18 | ] 19 | }) 20 | export class XtnActionSheet implements OnInit, AfterContentInit { 21 | @Input('ActionSheetInfo') Info: any; 22 | TriggerStateName: any; 23 | @Input('Index') __Index: number; 24 | constructor() { } 25 | 26 | ngOnInit() { 27 | } 28 | 29 | ngAfterContentInit(): void { 30 | const { ToPage } = this.Info; 31 | if (ToPage) { 32 | const { Url, Params } = ToPage; 33 | if (Url) { 34 | setTimeout(() => { 35 | Utility.$ToPage(Url, Params); 36 | }, 1500); 37 | } 38 | } 39 | this.TriggerStateName = 'down'; 40 | setTimeout(() => { 41 | this.TriggerStateName = 'up'; 42 | }, 2); 43 | setTimeout(() => { 44 | this.__ClickClose(); 45 | }, 1000); 46 | } 47 | ngAfterContentChecked(): void { 48 | const { IsClose } = this.Info; 49 | if (!!IsClose && this.TriggerStateName === 'up') { 50 | this.TriggerStateName = 'down'; 51 | } 52 | } 53 | 54 | __ClickClose() { 55 | this.TriggerStateName = 'down'; 56 | Utility.$ActionSheetHide(this.__Index); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/app/components/model/Core.ts: -------------------------------------------------------------------------------- 1 | import { XtnActionSheet } from './ActionSheet/ActionSheet'; 2 | import { XtnLoading } from './Loading/Loading'; 3 | import { XtnDialog } from './Dialog/Dialog'; 4 | 5 | export const XtnModel = [XtnActionSheet, XtnDialog, XtnLoading]; -------------------------------------------------------------------------------- /src/app/components/model/Dialog/Dialog.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 |
7 |
{{DialogInfo.Title}}
8 |
9 |
10 |
11 |
12 | 13 |
14 |
15 |
确定
16 |
取消
17 |
18 |
19 |
-------------------------------------------------------------------------------- /src/app/components/model/Dialog/Dialog.scss: -------------------------------------------------------------------------------- 1 | .dialogCss { 2 | position: fixed; 3 | z-index: 999; 4 | display: -webkit-box; 5 | -webkit-box-align: center; 6 | -webkit-box-pack: center; 7 | width: 100%; 8 | height: 100%; 9 | font-size: 12px; 10 | top: 0; 11 | 12 | .bgInfo { 13 | background: rgba(0, 0, 0, 0.2); 14 | height: 100%; 15 | width: 100%; 16 | position: fixed; 17 | } 18 | 19 | .content { 20 | position: relative; 21 | background: #fff; 22 | margin: 10px; 23 | border-radius: 5px; 24 | 25 | .title { 26 | text-align: center; 27 | padding: 5px 10px; 28 | border-bottom: 1px solid #ddddf3; 29 | } 30 | 31 | .data { 32 | padding: 0px; 33 | } 34 | 35 | .btns { 36 | display: flex; 37 | border-top: 1px solid #f5dfdf; 38 | 39 | > div { 40 | flex: 1; 41 | padding: 10px; 42 | text-align: center; 43 | } 44 | 45 | .confirm { 46 | &:active { 47 | border-bottom-left-radius: 5px; 48 | background: aliceblue; 49 | color: #222; 50 | } 51 | 52 | &:hover { 53 | background: rgba(208, 223, 234, 0.44); 54 | } 55 | } 56 | 57 | .cancel { 58 | border-left: 1px solid #f5dfdf; 59 | 60 | &:hover { 61 | background: rgba(208, 223, 234, 0.44); 62 | } 63 | 64 | &:active { 65 | border-bottom-right-radius: 5px; 66 | background: aliceblue; 67 | color: #222; 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/app/components/model/Dialog/Dialog.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EventEmitter, Component, OnInit, Output, OnChanges, Input, ViewChild, ReflectiveInjector, 3 | ViewContainerRef, ComponentFactoryResolver, ComponentRef, OnDestroy, AfterContentInit, 4 | DoCheck, AfterContentChecked, 5 | trigger, state, style, transition, animate 6 | } from '@angular/core'; 7 | import { Utility, OnDialog } from '../../Core'; 8 | 9 | @Component({ 10 | selector: 'xtn-mode-dialog', 11 | templateUrl: './Dialog.html', 12 | styleUrls: ['./Dialog.scss'], 13 | animations: [ 14 | trigger('TriggerState', [ 15 | state('inactive', style({ transform: 'scale(0.1)' })), 16 | state('active', style({ transform: 'scale(1)' })), 17 | transition('inactive => active', animate('150ms ease-in')), 18 | transition('active => inactive', animate('150ms ease-out')), 19 | ]) 20 | ] 21 | }) 22 | export class XtnDialog implements OnInit, OnDestroy, OnChanges, AfterContentChecked, AfterContentInit { 23 | @Input('DialogInfo') DialogInfo: any; // 对话框信息 24 | @Input('Index') __Index: number; 25 | @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef; // 组件要存放的地方 26 | compRef: ComponentRef; // 加载的组件实例 27 | 28 | TriggerStateName: any; 29 | 30 | constructor(private resolver: ComponentFactoryResolver) { 31 | } 32 | 33 | ngOnInit() { 34 | } 35 | 36 | ngOnChanges(): void { 37 | } 38 | 39 | ngAfterContentChecked(): void { 40 | const { IsClose } = this.DialogInfo; 41 | if (!!IsClose && this.TriggerStateName !== 'inactive') { 42 | this.TriggerStateName = 'inactive'; 43 | } 44 | } 45 | 46 | ngOnDestroy(): void { 47 | if (this.compRef) { 48 | this.compRef.destroy(); 49 | } 50 | } 51 | 52 | ngAfterContentInit(): void { 53 | const { IsLoadingComponent } = this.DialogInfo; 54 | if (!!IsLoadingComponent) { 55 | this.LoadComponent(this); 56 | } 57 | this.TriggerStateName = 'inactive'; 58 | setTimeout(() => { 59 | this.TriggerStateName = 'active'; 60 | }, 5); 61 | } 62 | 63 | /** 64 | * 加载组件 65 | * 66 | * @param {*} self 67 | * @returns 68 | * @memberof XtnDialog 69 | */ 70 | LoadComponent(self: any) { 71 | let { ComponentName, Params } = this.DialogInfo; 72 | let __Component; 73 | let fact = self.resolver._factories; 74 | // 根据名称,摸查出组件名称 75 | fact.forEach((value: any, key: any) => { 76 | if (key.name === ComponentName) { 77 | __Component = key; 78 | } 79 | }); 80 | 81 | if (!__Component) { 82 | return; 83 | } 84 | 85 | // 参数设置 86 | if (!Params) { 87 | Params = {}; 88 | } 89 | let inputProviders = Object.keys(Params).map((inputName) => { 90 | return { provide: inputName, useValue: Params[inputName] }; 91 | }); 92 | let resolvedInputs = ReflectiveInjector.resolve(inputProviders); 93 | let injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.container.parentInjector); 94 | if (this.compRef) { 95 | this.compRef.destroy(); 96 | } 97 | 98 | let factory = this.resolver.resolveComponentFactory(__Component); 99 | // 创建带参数的组件 100 | this.compRef = factory.create(injector); 101 | const { Outputs, Inputs } = Params; 102 | const __self = this; 103 | const { inputs, outputs } = factory; 104 | // 向组件传递参数。 105 | inputs.forEach((item) => { 106 | const { propName, templateName } = item; 107 | const inProps = Inputs[templateName]; 108 | // 给组件上的参数赋值操作。 109 | if (inProps) { 110 | __self.compRef.instance[propName] = Inputs[templateName]; 111 | } 112 | }); 113 | // 向外输入参数,这里主要是判断事件处理。 114 | outputs.forEach((row) => { 115 | const { propName, templateName } = row; 116 | const outProps = __self.compRef.instance[row.propName]; 117 | if (outProps as EventEmitter) { 118 | // 订阅事件处理 119 | outProps.subscribe((data) => { 120 | if (Outputs[templateName]) { 121 | Outputs[templateName](data) 122 | } 123 | }); 124 | } 125 | }); 126 | // 呈现组件的视图 127 | this.container.insert(this.compRef.hostView); 128 | } 129 | 130 | onClose() { 131 | Utility.$ShowDialogHide(this.__Index); 132 | } 133 | 134 | onClickClose() { 135 | this.onClose(); 136 | } 137 | 138 | btnClickCancel() { 139 | if (this.compRef) { 140 | if (this.compRef.instance.onDialogCancel) { 141 | this.compRef.instance.onDialogCancel(this); 142 | } 143 | } else { 144 | this.onClickClose(); 145 | } 146 | } 147 | 148 | btnClickConfirm() { 149 | if (this.compRef) { 150 | if (this.compRef.instance.onDialogConfirm) { 151 | this.compRef.instance.onDialogConfirm(this); 152 | } 153 | } else { 154 | this.onClickClose(); 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/app/components/model/Loading/Loading.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/components/model/Loading/Loading.html -------------------------------------------------------------------------------- /src/app/components/model/Loading/Loading.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/components/model/Loading/Loading.scss -------------------------------------------------------------------------------- /src/app/components/model/Loading/Loading.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, Input } from '@angular/core'; 2 | import { Utility } from '../../Core'; 3 | @Component({ 4 | selector: 'xtn-mode-loading', 5 | templateUrl: './Loading.html', 6 | styleUrls: ['./Loading.scss'] 7 | }) 8 | export class XtnLoading implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/components/navbar/navbar.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/navbar/navbar.component.scss: -------------------------------------------------------------------------------- 1 | .navbarCss { 2 | position: fixed; 3 | width: 100%; 4 | top: 0px; 5 | z-index: 1000; 6 | padding: 5px; 7 | background: blue; 8 | color: #fff; 9 | font-size: 20px; 10 | display: flex; 11 | .left, 12 | .right { 13 | width: 30px; 14 | } 15 | .center { 16 | flex: 1; 17 | text-align: center; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/app/components/navbar/navbar.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NavbarComponent } from './navbar.component'; 4 | 5 | describe('NavbarComponent', () => { 6 | let component: NavbarComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ NavbarComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NavbarComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/navbar/navbar.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, Input } from '@angular/core'; 2 | import { Utility } from '../../Common/Utility'; 3 | @Component({ 4 | selector: 'xtn-navbar', 5 | templateUrl: './navbar.component.html', 6 | styleUrls: ['./navbar.component.scss'] 7 | }) 8 | export class NavbarComponent implements OnInit { 9 | 10 | @Input('Title') __Title: string; 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | __GoBack() { 18 | Utility.$GoBack(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/app/components/rule/RuleInfo.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 返回结果索引 4 | 5 | 参数字段 6 | 7 |
8 |
9 |
添加
10 |
11 |
12 |
13 |
14 | 15 |
16 |
-------------------------------------------------------------------------------- /src/app/components/rule/RuleInfo.scss: -------------------------------------------------------------------------------- 1 | .runInfoCss { 2 | 3 | .ruleList { 4 | font-size: 16px; 5 | } 6 | 7 | .ruleTitle { 8 | border-bottom: 1px solid; 9 | padding: 1px 10px; // font-size: 16px; 10 | display: flex; 11 | align-items: center; 12 | 13 | span { 14 | padding-right: 5px; 15 | } 16 | 17 | .params { 18 | padding-left: 5px; 19 | } 20 | 21 | .number { 22 | width: 60px; 23 | } 24 | 25 | .fields { 26 | flex: 1; 27 | } 28 | } 29 | 30 | .rule { 31 | padding: 0px 10px; 32 | border: 1px solid #dea7e9; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app/components/rule/RuleInfo.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, Input, EventEmitter, OnChanges } from '@angular/core'; 2 | import { Utility } from '../Core'; 3 | @Component({ 4 | selector: 'xtn-rule-info', 5 | templateUrl: './RuleInfo.html', 6 | styleUrls: ['./RuleInfo.scss'] 7 | }) 8 | export class RuleInfo implements OnInit, OnChanges { 9 | 10 | @Input('Source') Info: any; 11 | @Input('Index') Index: number; 12 | @Input('IsExpanded') IsExpanded: boolean; 13 | stateExpression: string = 'collapsed'; 14 | 15 | @Output() onDelete: EventEmitter = new EventEmitter(); 16 | 17 | public RuleType: Array = [ 18 | { key: 'query', title: '查询' }, 19 | { key: 'update', title: '更新' }, 20 | { key: 'insert', title: '插入' }, 21 | { key: 'delete', title: '删除' }, 22 | { key: 'beginTran', title: '开始事务' }, 23 | { key: 'commit', title: '提交事务' }, 24 | { key: 'judge', title: '条件判断' }, 25 | ]; 26 | 27 | constructor() { 28 | } 29 | 30 | ngOnInit() { 31 | 32 | } 33 | ngOnChanges(): void { 34 | // this.stateExpression = !!this.IsExpanded ? 'expanded' : 'collapsed'; 35 | } 36 | 37 | onItemMoveUpOrDown(args, currentIndex) { 38 | const { type, index, OperatorType } = args; 39 | switch (type) { 40 | case OperatorType.UP: 41 | case OperatorType.DOWN: 42 | const currentItem = this.Info.rules[currentIndex]; 43 | const newItem = this.Info.rules[index]; 44 | this.Info.rules[index] = currentItem; 45 | this.Info.rules[currentIndex] = newItem; 46 | break; 47 | 48 | case OperatorType.INSERT: 49 | this.Info.rules.splice(currentIndex, 0, {}); 50 | break; 51 | case OperatorType.DELETE: 52 | this.Info.rules.splice(currentIndex, 1); 53 | break; 54 | } 55 | } 56 | 57 | onClickAdd() { 58 | let { rules } = this.Info; 59 | if (!rules) { 60 | rules = []; 61 | this.Info.rules = rules; 62 | } 63 | rules.push({}); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/app/components/rule/RuleItem.scss: -------------------------------------------------------------------------------- 1 | .rulItemCss { 2 | display: flex; 3 | .row { 4 | padding-top: 5px; 5 | 6 | .title { 7 | // padding: 5px; 8 | display: flex; 9 | 10 | .name { 11 | margin-right: 5px; 12 | width: 50px; 13 | text-align: right; 14 | } 15 | } 16 | 17 | input[type='number'] { 18 | width: 50px; 19 | } 20 | 21 | input[type='text'] { 22 | width: 100px; 23 | } 24 | } 25 | 26 | textarea { 27 | height: 100%; 28 | padding: 5px; 29 | width: calc(100% - 10px); 30 | min-height: 50px; 31 | font-size: 14px; 32 | height: 75px; 33 | } 34 | 35 | .right { 36 | flex: 1; 37 | position: relative; 38 | 39 | .oper { 40 | display: flex; 41 | align-items: center; 42 | font-weight: 800; 43 | position: absolute; 44 | right: 0px; 45 | background: #fff; 46 | border: 1px solid #c5beb4; 47 | background: #efe3e3; 48 | border: 1px solid #c5beb4; 49 | color: black; 50 | } 51 | 52 | .sqlInfo { 53 | flex: 1; 54 | height: 100%; 55 | .title { 56 | padding: 8px; 57 | } 58 | } 59 | 60 | .judgeInfo { 61 | @extend .sqlInfo; 62 | 63 | .bewrite { 64 | font-weight: 900; 65 | display: flex; 66 | align-items: center; 67 | padding: 6px; 68 | .failMsg { 69 | margin-left: 5px; 70 | flex: 1; 71 | display: flex; 72 | 73 | input { 74 | flex: 1; 75 | } 76 | } 77 | } 78 | 79 | .judgeType { 80 | display: flex; 81 | white-space: nowrap; 82 | align-items: center; 83 | 84 | >textarea { 85 | margin-left: 5px; 86 | } 87 | } 88 | 89 | .eveal { 90 | display: none; 91 | } 92 | } 93 | 94 | .setValue { 95 | flex: 1; 96 | 97 | .item { 98 | display: flex; 99 | 100 | input { 101 | flex: 1; 102 | width: 100%; 103 | margin-left: 5px; 104 | } 105 | 106 | .new { 107 | display: flex; 108 | white-space: nowrap; 109 | align-items: center; 110 | } 111 | 112 | .set { 113 | flex: 1; 114 | margin-left: 5px; 115 | align-items: center; 116 | display: flex; 117 | white-space: nowrap; 118 | } 119 | } 120 | } 121 | 122 | .relation { 123 | position: relative; 124 | .desc { 125 | padding: 8px; 126 | } 127 | .content { 128 | .idInfo { 129 | display: flex; 130 | align-items: center; 131 | 132 | input[type='number'] { 133 | width: 50px; 134 | } 135 | input [type='text'] { 136 | width: 100px; 137 | } 138 | } 139 | .fields { 140 | position: relative; 141 | 142 | .fieldRelation { 143 | display: flex; 144 | align-items: center; 145 | } 146 | } 147 | } 148 | } 149 | 150 | .captcha { 151 | border: 1px solid; 152 | min-height: 90px; 153 | .desc { 154 | padding: 0px; 155 | } 156 | } 157 | .files { 158 | border: 1px solid; 159 | min-height: 90px; 160 | 161 | .row { 162 | margin-left: 5px; 163 | margin-top: 2px; 164 | align-items: center; 165 | >label { 166 | width: 60px; 167 | text-align: right; 168 | } 169 | select, 170 | input[type='text'] { 171 | width: 100px; 172 | } 173 | } 174 | 175 | .desc { 176 | padding: 5px; 177 | color: red; 178 | font-weight: 700; 179 | line-height: 1.8; 180 | } 181 | 182 | .relation { 183 | .tableInfo { 184 | border-bottom: 2px solid; 185 | 186 | .tableName { 187 | border-bottom: 1px solid #e0e0e0; 188 | display: flex; 189 | align-items: center; 190 | input { 191 | flex: 1; 192 | width: 100%; 193 | } 194 | button { 195 | margin: 0px 5px; 196 | } 197 | } 198 | 199 | .relaField { 200 | display: flex; 201 | white-space: nowrap; 202 | align-items: center; 203 | input { 204 | flex: 1; 205 | width: 100%; 206 | } 207 | } 208 | } 209 | 210 | >div:last-child { 211 | border-bottom: none; 212 | } 213 | } 214 | } 215 | } 216 | } 217 | 218 | .chilren { 219 | margin-left: 15px; 220 | border: 1px solid #f410f0; 221 | 222 | .title { 223 | display: flex; 224 | align-items: center; 225 | 226 | .desc { 227 | padding-right: 10px; 228 | } 229 | 230 | .resultIndex { 231 | >span { 232 | padding: 0 5px; 233 | } 234 | } 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/app/components/rule/RuleItem.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, Input, EventEmitter } from '@angular/core'; 2 | import { Utility } from '../Core'; 3 | @Component({ 4 | selector: 'xtn-rule-item', 5 | templateUrl: './RuleItem.html', 6 | styleUrls: ['./RuleItem.scss'] 7 | }) 8 | export class RuleItem implements OnInit { 9 | 10 | @Input('Source') Rule: any; 11 | @Input('Index') Index: number; 12 | @Input('ParentId') ParentId: number; 13 | @Input('IsFirst') IsFirst: Boolean; 14 | @Input('IsLast') IsLast: Boolean; 15 | 16 | @Output() onMoveUpOrDown: EventEmitter = new EventEmitter(); 17 | 18 | 19 | public OperatorType: any = { 20 | UP: 'move_up', 21 | DOWN: 'move_down', 22 | INSERT: 'insert', 23 | DELETE: 'delete', 24 | } 25 | 26 | FileTypes: Array = [ 27 | { key: 'image', title: '图片' }, 28 | { key: 'video', title: '视频' }, 29 | { key: 'doc', title: '文档' }, 30 | { key: 'other', title: '其它' }, 31 | ]; 32 | private defaultFileInfo: any = [{ TableName: '', Fields: [{}] }]; 33 | 34 | public RuleType: Array = [ 35 | { key: 'query', title: '查询' }, 36 | { key: 'update', title: '更新' }, 37 | { key: 'insert', title: '插入' }, 38 | { key: 'delete', title: '删除' }, 39 | { key: 'beginTran', title: '开始事务' }, 40 | { key: 'commit', title: '提交事务' }, 41 | { key: 'judge', title: '条件判断' }, 42 | { key: 'cache', title: '保存到缓存' }, 43 | { key: 'setvalue', title: '赋值操作' }, 44 | { key: 'parentrelation', title: '主子关系' }, 45 | { key: 'captcha', title: '验证码' }, 46 | { key: 'files', title: '文件上传' }, 47 | { key: 'apiCall', title: '调用第三方API' }, 48 | ]; 49 | public ThirdPartyApiMethod: Array = [ 50 | { key: 'get', title: 'get' }, 51 | { key: 'delete', title: 'delete' }, 52 | { key: 'post', title: 'post' }, 53 | { key: 'put', title: 'put' }, 54 | ]; 55 | 56 | constructor() { 57 | 58 | const tf = this.FileTypes[0]; 59 | this.defaultFileInfo = { 60 | type: tf.key, filePath: './public/' + tf.key, 61 | filePathField: 'filepath', 62 | fileNameField: 'filename', 63 | Relations: [{ TableName: '', Fields: [] }], 64 | // Relation: { 65 | // TableName: '', 66 | // Fields: [{}] 67 | // } 68 | } 69 | } 70 | 71 | ngOnInit(): void { 72 | if (this.Index >= 0 && !this.Rule.id) { 73 | if (this.ParentId) { 74 | this.Rule.id = this.ParentId * 100 + this.Index; 75 | } else { 76 | this.Rule.id = this.Index + 1; 77 | } 78 | } 79 | 80 | 81 | let { type } = this.Rule; 82 | const { judgeInfo, setValues, parentRelation, captcha, files, apiCall } = this.Rule; 83 | if (!type) { // 查询操作 84 | this.Rule.type = 'query'; 85 | } else if (type === 'judge') { // 判断操作 86 | if (!judgeInfo) { 87 | this.Rule.judgeInfo = {}; 88 | } 89 | } else if (type === 'setvalue') { // 赋值操作 90 | if (!setValues) { 91 | this.Rule.setValues = []; 92 | } 93 | } else if (type === 'parentRelation'.toLocaleLowerCase()) { // 主表与从表的关系 94 | if (!parentRelation) { 95 | this.Rule.parentRelation = { fields: [] } 96 | } 97 | } else if (type === 'captcha' && !captcha) { // 验证码 98 | this.Rule.captcha = {}; 99 | } else if (type === 'files') { // 文件关系 100 | if (!files) { 101 | this.Rule.files = this.defaultFileInfo; // { type: tf.key, filePath: './public/' + tf.key }; 102 | } else { 103 | let { Relation, Relations } = files; 104 | if (!Relations) { 105 | Relations = []; 106 | files.Relations = Relations; 107 | Relations.push(Relation || { TableName: '', Fields: [{}] }); 108 | } 109 | } 110 | } else if (type === 'apiCall' && !apiCall) { 111 | this.Rule.apiCall = {}; 112 | } 113 | } 114 | 115 | onChange_RuleType(item) { 116 | const { type, judgeInfo, files, cacheInfo, setValues, parentRelation, captcha, apiCall } = this.Rule; 117 | if (item === 'judge' && !judgeInfo) { 118 | this.Rule.judgeInfo = {}; 119 | } else if (item === 'cache' && !cacheInfo) { 120 | this.Rule.cacheInfo = {}; 121 | } else if (item === 'setvalue' && !setValues) { 122 | this.Rule.setValues = []; 123 | } else if (item === 'parentRelation'.toLocaleLowerCase() && !parentRelation) { 124 | this.Rule.parentRelation = { fields: [] } 125 | } else if (type === 'captcha' && !captcha) { 126 | this.Rule.captcha = {}; 127 | } else if (type === 'file' && !files) { 128 | // const tf = this.FileTypes[0]; 129 | // this.Rule.files = { type: tf.key, filePath: './public/' + tf.key }; 130 | this.Rule.files = this.defaultFileInfo; 131 | } else if (type === 'apiCall' && !apiCall) { 132 | this.Rule.apiCall = {}; 133 | } 134 | } 135 | 136 | btn_Click(type, index) { 137 | if (this.onMoveUpOrDown) { 138 | this.onMoveUpOrDown.emit({ type, index, OperatorType: this.OperatorType }); 139 | } 140 | } 141 | 142 | onChange_FileType(type) { 143 | console.log(type); 144 | this.Rule.files.filePath = './public/' + type; 145 | } 146 | 147 | onClickAddRule(rule) { 148 | let { chilrenRules } = rule; 149 | if (!Array.isArray(chilrenRules)) { 150 | chilrenRules = []; 151 | rule.chilrenRules = chilrenRules; 152 | } 153 | chilrenRules.push({ judgeInfo: {} }); 154 | } 155 | 156 | onSubItemMoveUpOrDown(args, currentIndex) { 157 | const { type, index, OperatorType } = args; 158 | const rules = this.Rule.judgeInfo.chilrenRules; 159 | switch (type) { 160 | case OperatorType.UP: 161 | case OperatorType.DOWN: 162 | const currentItem = rules[currentIndex]; 163 | const newItem = rules[index]; 164 | rules[index] = currentItem; 165 | rules[currentIndex] = newItem; 166 | break; 167 | case OperatorType.INSERT: 168 | rules.splice(currentIndex, 0, JSON.parse(JSON.stringify(rules[currentIndex]))); 169 | break; 170 | case OperatorType.DELETE: 171 | rules.splice(currentIndex, 1); 172 | break; 173 | } 174 | } 175 | 176 | onClickAddSetvalue() { 177 | const { judgeInfo, setValues } = this.Rule; 178 | setValues.push({}); 179 | } 180 | 181 | onBtnClickAddRelation() { 182 | console.log('---------------onBtnClickAddRelation--------'); 183 | let { fields } = this.Rule.parentRelation; 184 | if (!fields) { 185 | fields = []; 186 | this.Rule.parentRelation.fields = fields; 187 | } 188 | fields.push({}); 189 | } 190 | 191 | onBtnClickDeleteField(index) { 192 | this.Rule.parentRelation.fields.splice(index, 1); 193 | } 194 | 195 | onClickCaptcha() { 196 | this.Rule.captcha.isDelete = !this.Rule.captcha.isDelete; 197 | } 198 | 199 | btnDeleteFileRelationField(index, fileds) { 200 | if (fileds.length > 1) { 201 | fileds.splice(index, 1); 202 | } 203 | } 204 | 205 | btnAddFileRelationField(index, fields) { 206 | fields.splice(index + 1, 0, {}); 207 | } 208 | 209 | btnAddTableRelation(index, tables) { 210 | console.log('btnAddTableRelation', tables); 211 | tables.splice(index + 1, 0, { TableName: '', Fields: [{}] }); 212 | } 213 | 214 | btnDeleteTableRelation(index, tables) { 215 | console.log('btnDeleteTableRelation', tables); 216 | if (tables.length > 1) { 217 | tables.splice(index, 1); 218 | } 219 | 220 | } 221 | 222 | btnClickThirdPartyApi(apiParam, index, apiParamList, operator) { 223 | if (operator === 1) { 224 | if (index === -1) { 225 | if (!apiParamList) { 226 | apiParamList = []; 227 | this.Rule.apiCall.ApiHeaderParams = apiParamList; 228 | } 229 | } 230 | apiParamList.splice(index + 1, 0, {}); 231 | return; 232 | } 233 | 234 | apiParamList.splice(index, 1); 235 | } 236 | 237 | btnClickThirdPartyApiBody(apiParam, index, apiParamList, operator) { 238 | if (operator === 1) { 239 | if (index === -1) { 240 | if (!apiParamList) { 241 | apiParamList = []; 242 | this.Rule.apiCall.ApiBodyParams = apiParamList; 243 | } 244 | } 245 | apiParamList.splice(index + 1, 0, {}); 246 | return; 247 | } 248 | apiParamList.splice(index, 1); 249 | } 250 | 251 | onClickSetFixedValue(item) { 252 | item.IsFixedValue = !item.IsFixedValue; 253 | } 254 | 255 | } -------------------------------------------------------------------------------- /src/app/containers/Core.ts: -------------------------------------------------------------------------------- 1 | export { ServiceHelper } from '../manage/Core' 2 | export { Client } from '../helpers/Core'; 3 | export { Utility } from '../Common/Utility'; 4 | export { routeAnimation } from './app.animations'; 5 | export { BaseComponent } from './base.component'; -------------------------------------------------------------------------------- /src/app/containers/Index.ts: -------------------------------------------------------------------------------- 1 | export { CommonComponent } from '../components/Index' 2 | import { MyComponent } from './my-component/my-component.component'; 3 | import { Product } from './product/product.component'; 4 | import { Members } from './members/members.component'; 5 | import { NotFound } from './not-found/not-found.component'; 6 | import { Home } from './home/home.component'; 7 | import { BaiduMapPage } from './baidu-map/Index'; 8 | 9 | const __Router = { ...BaiduMapPage, Home, MyComponent, Members, Product, NotFound }; 10 | const __Keys = Object.keys(__Router); 11 | 12 | const __PageList = []; 13 | __Keys.forEach((key) => { 14 | __PageList.push(__Router[key]); 15 | }); 16 | 17 | export const RouterComponent = __Router; 18 | export const PageComponentList = __PageList; -------------------------------------------------------------------------------- /src/app/containers/app.animations.ts: -------------------------------------------------------------------------------- 1 | import { animate, AnimationEntryMetadata, state, style, transition, trigger } from '@angular/core'; 2 | 3 | const { height } = screen; 4 | const __top = 36; 5 | const __height = (height - __top) / height * 100; 6 | 7 | const __style = { 8 | position: 'fixed', width: '100%', left: '0px', top: '0px', paddingTop: __top + 'px', 9 | height: __height + '%', overflow: 'auto' 10 | }; 11 | export const routeAnimation: AnimationEntryMetadata = [ 12 | 13 | trigger('routing', [ // paddingTop 添加这个是为了导航长的高度。 14 | state('void', style(__style)), 15 | state('*', style(__style)), 16 | // state('void', style({ position: 'fixed', width: '100%', left: '0px', })), 17 | // state('*', style({ position: 'fixed', width: '100%', left: '0px', })), 18 | // 上一页 19 | transition('void => backward', [style({ transform: 'translateX(-100%)' }), animate('0.4s ease-in-out', style({ transform: 'translateX(0%)' }))]), 20 | transition('backward => void', [style({ transform: 'translateX(0%)' }), animate('0.4s ease-in-out', style({ transform: 'translateX(100%)' }))]), 21 | // 下一页 22 | transition('void => forward', [style({ transform: 'translateX(100%)' }), animate('0.4s ease-in-out', style({ transform: 'translateX(0%)' }))]), 23 | transition('forward => void', [style({ transform: 'translateX(0%)' }), animate('0.4s ease-in-out', style({ transform: 'translateX(-100%)' }))]) 24 | ]) 25 | ] 26 | 27 | export function ToRight() { 28 | return trigger('routerTransition', [ 29 | state('void', style({ position: 'fixed', width: '100%', left: '0px' })), 30 | state('*', style({ position: 'fixed', width: '100%', left: '0px' })), 31 | transition(':enter', [style({ transform: 'translateX(-100%)' }), animate('11.5s ease-in-out', style({ transform: 'translateX(0%)' }))]), 32 | transition(':leave', [style({ transform: 'translateX(0%)' }), animate('11.5s ease-in-out', style({ transform: 'translateX(100%)' }))]) 33 | ]); 34 | } 35 | -------------------------------------------------------------------------------- /src/app/containers/baidu-map/Index.ts: -------------------------------------------------------------------------------- 1 | import { BaiduMap } from './baidu-map' 2 | import { BaiduMyPlaceList } from './MyPlaceList/MyPlaceList'; 3 | import { BaiduMyJoinPlace } from './MyJoinPlace/MyJoinPlace'; 4 | 5 | export const BaiduMapPage = { BaiduMyJoinPlace, BaiduMap, BaiduMyPlaceList }; -------------------------------------------------------------------------------- /src/app/containers/baidu-map/MyJoinPlace/MyJoinPlace.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

请输入邀请码

5 | 6 |
7 | 8 |
9 | 10 |
11 |
确定
12 |
13 |
-------------------------------------------------------------------------------- /src/app/containers/baidu-map/MyJoinPlace/MyJoinPlace.scss: -------------------------------------------------------------------------------- 1 | .myJoinPlace { 2 | position: relative; 3 | 4 | >h2 { 5 | text-align: center; 6 | } 7 | .InviteCode { 8 | // display: flex; 9 | position: relative; 10 | padding: 0px 20%; 11 | 12 | >input { 13 | width: 100%; 14 | margin-top: 10px; // padding: 5px 10px; 15 | text-align: center; 16 | // flex: 1; 17 | font-size: 30px; 18 | border-radius: 10px; 19 | border: 1px solid darkgray; 20 | outline-style: none; 21 | } 22 | } 23 | 24 | .btns { 25 | padding: 5px 10px; 26 | margin-top: 30px; 27 | .btn { 28 | text-align: center; 29 | flex: 1; 30 | border: 1px solid; 31 | font-size: 18px; 32 | border-radius: 5px; 33 | padding: 5px 10px; 34 | background: blue; 35 | color: #fbf1f1; 36 | &:active { 37 | background: #6855d4; 38 | } 39 | &:hover { 40 | background: #a4a4ca; 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/app/containers/baidu-map/MyJoinPlace/MyJoinPlace.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Utility, ServiceHelper, routeAnimation, BaseComponent } from '../../Core'; 3 | 4 | 5 | @Component({ 6 | selector: 'app-baidu-map-my-join-place', 7 | templateUrl: 'MyJoinPlace.html', 8 | styleUrls: ['./MyJoinPlace.scss'], 9 | animations: [routeAnimation], 10 | providers: [ServiceHelper] 11 | }) 12 | export class BaiduMyJoinPlace extends BaseComponent implements OnInit { 13 | 14 | InviteCode: any; 15 | 16 | constructor(private sHelper: ServiceHelper) { 17 | super(); 18 | } 19 | 20 | ngOnInit() { 21 | 22 | } 23 | 24 | onClickOk() { 25 | console.log(this.InviteCode); 26 | if (!this.InviteCode || this.InviteCode === '') { 27 | Utility.$ShowMessage('参加活动', '请输入你的邀请码?'); 28 | return; 29 | } 30 | this.sHelper.BaiduMap.JoinPlace(this.InviteCode).then(() => { }, () => { }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/containers/baidu-map/MyPlaceList/MyPlaceList.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 |
8 |
9 |
10 |
活动名称: {{item.Name}}
11 |
邀请码:{{item.InviteCode}}
12 | 13 |
14 |
查看位置
15 |
16 |
17 |
地点: {{item.Address}}
18 |
时间:{{item.BeginDate|date:'yyyy-MM-dd HH:mm'}} ~ {{item.EndDate|date:'yyyy-MM-dd HH:mm'}}
19 |
20 | 描述:{{item.Bewrite}} 21 |
22 |
23 |
24 | {{people.username}} 25 |
26 |
27 |
28 |
29 |
-------------------------------------------------------------------------------- /src/app/containers/baidu-map/MyPlaceList/MyPlaceList.scss: -------------------------------------------------------------------------------- 1 | .myPlaceListCss { 2 | position: relative; 3 | height: 100%; 4 | width: 100%; 5 | font-size: 12px; 6 | 7 | .place { 8 | padding: 10px; 9 | 10 | .row { 11 | border: 1px solid #f1f1f1; 12 | margin-bottom: 5px; 13 | border-radius: 5px; 14 | padding: 5px; 15 | 16 | &:hover { 17 | border: 1px solid #c0c0e6; 18 | background: rgba(208, 223, 234, 0.44); 19 | } 20 | 21 | &:active { 22 | background: aliceblue; 23 | } 24 | 25 | .nameInviteCode { 26 | padding: 5px 0; 27 | align-items: center; 28 | position: relative; 29 | 30 | .name { 31 | >span { 32 | font-size: 120%; 33 | color: #222; 34 | font-weight: 600; 35 | } 36 | } 37 | 38 | .invite { 39 | margin-top: 5px; 40 | 41 | >span { 42 | color: Red; 43 | font-size: 120%; 44 | } 45 | } 46 | 47 | .toMap { 48 | position: absolute; 49 | top: 0; 50 | right: 0; 51 | 52 | >div { 53 | padding: 5px 15px; 54 | border-radius: 5px; 55 | border: 1px solid #868689; 56 | font-size: 110%; 57 | background: #222; 58 | color: #fff; 59 | } 60 | } 61 | } 62 | 63 | .address { 64 | @extend .nameInviteCode; 65 | } 66 | 67 | .time { 68 | @extend .nameInviteCode; 69 | } 70 | 71 | .bewrite { 72 | @extend .nameInviteCode; 73 | } 74 | 75 | .peopleList { 76 | padding: 5px; 77 | display: flex; 78 | overflow: auto; 79 | .people { 80 | margin-right: 5px; 81 | padding: 5px 10px; 82 | white-space: nowrap; 83 | border: 1px solid; 84 | border-radius: 5px; 85 | } 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/app/containers/baidu-map/MyPlaceList/MyPlaceList.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Utility, ServiceHelper, routeAnimation, BaseComponent } from '../../Core'; 3 | 4 | 5 | @Component({ 6 | selector: 'app-baidu-map-place-list', 7 | templateUrl: 'MyPlaceList.html', 8 | styleUrls: ['./MyPlaceList.scss'], 9 | animations: [routeAnimation], 10 | providers: [ServiceHelper] 11 | }) 12 | export class BaiduMyPlaceList extends BaseComponent implements OnInit { 13 | 14 | PlaceList: any; 15 | 16 | constructor(private sHelper: ServiceHelper) { 17 | super(); 18 | } 19 | 20 | ngOnInit() { 21 | this.__InitMyPlacePlist(); 22 | } 23 | 24 | __InitMyPlacePlist() { 25 | 26 | const self = this; 27 | this.sHelper.BaiduMap.MyPlaceList({ PageIndex: 0, PageSize: 10 }).then(() => { 28 | self.PlaceList = self.sHelper.BaiduMap.PlaceListInfo; 29 | }, () => { 30 | 31 | }); 32 | 33 | } 34 | 35 | onBtnQuery() { 36 | this.__InitMyPlacePlist(); 37 | } 38 | 39 | onClickToMap(item) { 40 | if (!item) { 41 | return; 42 | } 43 | const { Id, Name, Longitude, Latitude } = item; 44 | this.sHelper.BaiduMap.CurrentPlaceInfo = item; 45 | Utility.$ToPage(Utility.$ConstItem.UrlItem.BaiduMap, { PlaceId: Id, Name, Longitude, Latitude }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/app/containers/baidu-map/baidu-map.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 6 |
7 |
8 | 15 |
后退
16 |
添加聚会地址
17 |
我发起的
18 |
我要加入
19 |
20 | 21 |
-------------------------------------------------------------------------------- /src/app/containers/baidu-map/baidu-map.scss: -------------------------------------------------------------------------------- 1 | .baiduMapCss { 2 | font-size: 12px; 3 | .allMap { 4 | position: relative; 5 | height: 92.3vh; 6 | width: 100%; 7 | top: 0; 8 | left: 0; 9 | 10 | >div { 11 | height: 100%; 12 | width: 100%; 13 | top: 0; 14 | left: 0; 15 | } 16 | } 17 | 18 | .groupBtn { 19 | position: absolute; 20 | z-index: 999; 21 | display: flex; 22 | flex-wrap: wrap; 23 | top: 0px; 24 | 25 | .btn { 26 | background: aliceblue; 27 | padding: 10px; 28 | border-right: 1px solid #f5e5e5; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/containers/baidu-map/baidu-map.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { BaiduMap } from './baidu-map'; 4 | 5 | describe('BaiduMap', () => { 6 | let component: BaiduMap; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ BaiduMap ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(BaiduMap); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/containers/base.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, HostBinding, OnInit } from '@angular/core'; 2 | import { routeAnimation } from './app.animations'; 3 | import { Utility } from './Core'; 4 | 5 | @Component({ 6 | moduleId: module.id, 7 | selector: 'selector', 8 | animations: [routeAnimation] 9 | }) 10 | export class BaseComponent implements OnInit { 11 | __Title: string = ''; 12 | UrlParams: any; 13 | 14 | @HostBinding("@routing") get routing() { 15 | const IsGoBack = Utility.$GetContent(Utility.$ConstItem.AppIsGoBack); 16 | return !!IsGoBack ? 'backward' : 'forward'; 17 | } 18 | // @HostBinding('style.display') display = "block"; 19 | 20 | 21 | constructor() { 22 | // get brower title 23 | this.__GetBrowerTitle(); 24 | this.UrlParams = Utility.$GetContent(Utility.$ConstItem.UrlPathInfo); 25 | } 26 | 27 | ngOnInit() { 28 | // this.UrlParams = Utility.$GetContent(Utility.$ConstItem.UrlPathInfo); 29 | } 30 | 31 | __GetBrowerTitle() { 32 | const titleServer: any = Utility.$GetContent(Utility.$ConstItem.BrowerTitle); 33 | if (titleServer && titleServer.getTitle) { 34 | this.__Title = titleServer.getTitle() || ''; 35 | } 36 | } 37 | 38 | routeFn(direction: string, nextRoute: string) { 39 | this.NextPage(nextRoute); 40 | } 41 | 42 | NextPage(url) { 43 | Utility.$ToPage(url, {}); 44 | } 45 | 46 | GoBack() { 47 | Utility.$GoBack(); 48 | } 49 | } -------------------------------------------------------------------------------- /src/app/containers/home/home.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
get
7 |
post
8 |
delete
9 |
put
10 |
11 | 弹出窗体1 12 |
13 |
14 | 弹出窗体2 15 |
16 |
17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 |
25 |
{{item.type}}
26 |
{{item.name}}
27 |
{{item.size}}
28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 | 38 | 40 |
41 |
42 |
{{item.AreaId}}
43 |
{{item.AreaName}}
44 |
45 |
46 |
47 |
-------------------------------------------------------------------------------- /src/app/containers/home/home.component.scss: -------------------------------------------------------------------------------- 1 | .homeCss { 2 | padding: 5px 1px; 3 | 4 | .apiResult { 5 | border: 1px solid #f5f5f5; 6 | 7 | .row { 8 | border: 1px solid #f5f5f5; 9 | display: flex; 10 | padding: 5px 0; 11 | margin-bottom: 5px; 12 | 13 | &:hover { 14 | background: blue; 15 | color: #fff; 16 | } 17 | 18 | .datetime, 19 | .id { 20 | white-space: nowrap; 21 | } 22 | 23 | .guid { 24 | white-space: nowrap; 25 | overflow: hidden; 26 | text-overflow: ellipsis; 27 | margin: 0 5px; 28 | } 29 | } 30 | } 31 | 32 | .demo { 33 | // padding: 10px; 34 | .btns { 35 | display: flex; 36 | flex-wrap: wrap; 37 | 38 | .btn { 39 | margin: 5px; 40 | padding: 5px 10px; 41 | text-align: center; 42 | border: 1px solid #f1f1f1; 43 | } 44 | } 45 | } 46 | 47 | .captcha { 48 | display: flex; 49 | >div { 50 | height: 50px; 51 | width: 100%; 52 | } 53 | 54 | button { 55 | white-space: nowrap; 56 | } 57 | } 58 | 59 | .fileUpload { 60 | margin-top: 10px; 61 | .file { 62 | display: flex; 63 | 64 | .name { 65 | flex: 1; 66 | } 67 | 68 | .type, 69 | size { 70 | margin: 0px 5px; 71 | } 72 | } 73 | } 74 | 75 | .areaInfo { 76 | display: flex; 77 | margin-bottom: 5px; 78 | border: 1px solid #e0e0e0; 79 | padding: 5px; 80 | border-radius: 5px; 81 | 82 | .name { 83 | margin-left: 5px; 84 | } 85 | } 86 | } 87 | 88 | .homeComCssEnd { 89 | font-size: 20px; 90 | color: red; 91 | } 92 | -------------------------------------------------------------------------------- /src/app/containers/home/home.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { Home } from './home.component'; 4 | 5 | describe('Home', () => { 6 | let component: Home; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ Home ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(Home); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/containers/home/home.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { DomSanitizer } from '@angular/platform-browser'; 3 | import { ServiceHelper, BaseComponent, routeAnimation, Utility, Client, } from '../Core'; 4 | 5 | @Component({ 6 | selector: 'app-home', 7 | templateUrl: './home.component.html', 8 | styleUrls: ['./home.component.scss'], 9 | animations: [routeAnimation], 10 | providers: [ServiceHelper] 11 | }) 12 | export class Home extends BaseComponent implements OnInit { 13 | tempData: any = '哈哈'; 14 | ScrollInfo: any; 15 | public DataList: Array; 16 | AreaInfo: any; 17 | CommonInfo: any; 18 | Catcha: any; 19 | 20 | constructor(private sHelper: ServiceHelper, private sanitizer: DomSanitizer) { 21 | super(); 22 | this.ScrollInfo = {}; 23 | this.CommonInfo = sHelper.Common; 24 | } 25 | 26 | ngOnInit() { 27 | // this.__ShowDialog(); 28 | this.__GetCaptcha(); 29 | } 30 | 31 | __GetCaptcha() { 32 | const self = this; 33 | this.sHelper.Common.GetCaptcha().then((result) => { 34 | self.Catcha = self.sanitizer.bypassSecurityTrustHtml(result); 35 | }, () => { }); 36 | } 37 | 38 | __UserInfo(methodType) { 39 | this.sHelper.DemoService.UserInfo(methodType).then((result) => { 40 | }, (a) => { 41 | }); 42 | } 43 | 44 | TestEvent(args) { 45 | console.log('test event-->', args); 46 | } 47 | 48 | __ShowDialog2() { 49 | Utility.$ShowDialogComponent('XtnConfirm', 50 | { Title: 'XtnConfirm组件' }, 51 | { 52 | onConfirm: (event) => { 53 | const { dialog, args } = event; 54 | console.log(args); 55 | dialog.onClose(); 56 | } 57 | }); 58 | 59 | } 60 | 61 | __ShowDialog() { 62 | Utility.$ShowDialogComponent('XtnMapPlaceItem', { 63 | Place: { Address: '就在这里啦', }, 64 | }, { 65 | onSave: (ee) => { 66 | Utility.$ShowMessage('标题', '这是弹出来的内容'); 67 | if (ee.dialog) { 68 | ee.dialog.onClose(); 69 | } 70 | }, 71 | onDelete: this.TestEvent.bind(this), 72 | onModify: (event) => { 73 | console.log('on modify--', event); 74 | }, 75 | }); 76 | } 77 | 78 | __GetArearData(Condition) { 79 | const { ScrollInfo } = this; 80 | const { Common } = this.sHelper; 81 | const self = this; 82 | Common.GetArea(Condition).then(() => { 83 | ScrollInfo.IsRefreshFinish = true; 84 | ScrollInfo.IsNextPageFinish = true; 85 | self.AreaInfo = Common.AreaInfo; 86 | }, () => { 87 | ScrollInfo.IsRefreshFinish = true; 88 | ScrollInfo.IsNextPageFinish = true; 89 | }); 90 | } 91 | 92 | onScrollRefresh() { 93 | this.ScrollInfo.IsRefreshFinish = false; 94 | this.__GetArearData(null); 95 | } 96 | 97 | onScrollNextPage() { 98 | this.ScrollInfo.IsNextPageFinish = false; 99 | const { AreaInfo } = this.sHelper.Common; 100 | this.__GetArearData(AreaInfo && AreaInfo.Condition ? AreaInfo.Condition : null); 101 | } 102 | 103 | onSlideLeft() { 104 | console.log('向左边滑动啦...'); 105 | } 106 | 107 | onSlideRight() { 108 | console.log('向右边滑动..'); 109 | } 110 | 111 | FileCollection: Array = new Array(); 112 | onTxtUpload(event) { 113 | console.log(event); 114 | const file = event.currentTarget.files[0]; 115 | this.FileCollection.push(file); 116 | } 117 | onBtnClickBatchUpload() { 118 | this.sHelper.Common.FilesUpload(this.FileCollection).then((success) => { 119 | console.log('file upload success.'); 120 | }, () => { }); 121 | 122 | } 123 | onBtnClickUpload() { 124 | this.sHelper.Common.FileUpload(this.FileCollection[0]).then((success) => { 125 | console.log('file upload success.'); 126 | }, () => { }); 127 | } 128 | 129 | onBtnDeleteFile(index) { 130 | console.log('onBtnDeleteFile----index is ', index); 131 | this.FileCollection.splice(index, 1); 132 | } 133 | 134 | onBtnCallApi() { 135 | this.sHelper.Common.CallOtherApi(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/app/containers/members/members.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |

{{title}}

6 | 7 |
-------------------------------------------------------------------------------- /src/app/containers/members/members.component.scss: -------------------------------------------------------------------------------- 1 | .memberCss { 2 | .bind1 { 3 | padding: 5px; 4 | border: 1px solid #222; 5 | display: flex; 6 | align-items: center; 7 | 8 | .id { 9 | font-size: 18px; 10 | padding: 5px; 11 | } 12 | 13 | .name { 14 | color: blue; 15 | padding-left: 15px; 16 | } 17 | } 18 | 19 | .bind2 { 20 | margin-top: 5px; 21 | 22 | .rowInfo { 23 | margin-top: 2px; 24 | @extend .bind1; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/app/containers/members/members.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { Members } from './members.component'; 4 | 5 | describe('Members', () => { 6 | let component: Members; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ Members ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(Members); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/containers/members/members.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { BaseComponent, Utility, routeAnimation } from '../Core'; 3 | 4 | @Component({ 5 | selector: 'app-members', 6 | templateUrl: './members.component.html', 7 | styleUrls: ['./members.component.scss'], 8 | animations: [routeAnimation] 9 | }) 10 | export class Members extends BaseComponent implements OnInit { 11 | title = "成员组件"; 12 | 13 | 14 | ngOnInit(): void { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/containers/my-component/my-component.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | my-component works! 5 |

-------------------------------------------------------------------------------- /src/app/containers/my-component/my-component.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/containers/my-component/my-component.component.scss -------------------------------------------------------------------------------- /src/app/containers/my-component/my-component.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { MyComponent } from './my-component.component'; 4 | 5 | describe('MyComponent', () => { 6 | let component: MyComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ MyComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(MyComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/containers/my-component/my-component.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { BaseComponent, Utility, routeAnimation } from '../Core'; 3 | 4 | @Component({ 5 | selector: 'app-my-component', 6 | templateUrl: './my-component.component.html', 7 | styleUrls: ['./my-component.component.scss'], 8 | animations: [routeAnimation] 9 | }) 10 | export class MyComponent extends BaseComponent implements OnInit { 11 | title = "page 3"; 12 | 13 | ngOnInit(): void { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/app/containers/not-found/not-found.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | not-found works! 5 |

-------------------------------------------------------------------------------- /src/app/containers/not-found/not-found.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/containers/not-found/not-found.component.scss -------------------------------------------------------------------------------- /src/app/containers/not-found/not-found.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NotFound } from './not-found.component'; 4 | 5 | describe('NotFound', () => { 6 | let component: NotFound; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ NotFound ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NotFound); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/containers/not-found/not-found.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-not-found', 5 | templateUrl: './not-found.component.html', 6 | styleUrls: ['./not-found.component.scss'] 7 | }) 8 | export class NotFound implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/containers/product/product.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | product works! 5 |

-------------------------------------------------------------------------------- /src/app/containers/product/product.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/containers/product/product.component.scss -------------------------------------------------------------------------------- /src/app/containers/product/product.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { Product } from './product.component'; 4 | 5 | describe('Product', () => { 6 | let component: Product; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ Product ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(Product); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should be created', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/containers/product/product.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { BaseComponent, Utility, routeAnimation } from '../Core'; 3 | 4 | @Component({ 5 | selector: 'app-product', 6 | templateUrl: './product.component.html', 7 | styleUrls: ['./product.component.scss'], 8 | animations: [routeAnimation] 9 | }) 10 | export class Product extends BaseComponent implements OnInit { 11 | 12 | title = "page 2"; 13 | 14 | ngOnInit(): void { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/helpers/ApiClient.ts: -------------------------------------------------------------------------------- 1 | import superagent from 'superagent'; 2 | import { Utility } from '../Common/Utility'; 3 | 4 | const methods = ['get', 'post', 'put', 'patch', 'del']; 5 | 6 | /** 7 | * 格式化URL 8 | * 9 | * @param {any} path 10 | * @returns 11 | */ 12 | function formatUrl(path) { 13 | const __path = path[0] !== '/' ? '/' + path : path; 14 | const _ApiUrl = 'https://127.0.0.1:30081/webapi' + __path; 15 | return _ApiUrl; 16 | } 17 | 18 | /** 19 | * 访问接口类 20 | * 21 | * @export 22 | * @class ApiClient 23 | */ 24 | export default class ApiClient { 25 | 26 | API = { 27 | Common: { 28 | /** 29 | * GET api/depts 获取组织机构 30 | * -------------------------------------参入的参数------------------------------------------- 31 | */ 32 | Organization: '/depts', 33 | /** 34 | * post 35 | */ 36 | SaveUser: '/saveUser', 37 | UserLogin: '/userinfo/user', 38 | AddUser: '/userinfo/register', 39 | Userlist: '/userinfo/users', 40 | DeleteUser: '/userinfo/user', 41 | Area: '/common/area', 42 | /** 43 | * get 根据Id获取信息 44 | */ 45 | AreaById: '/base/AreaById', 46 | Captcha: '/apihelper/captcha', 47 | FileUpload: '/apihelper/fileupload', 48 | FilesUpload: '/apihelper/filesupload', 49 | CallThirdPartyApi: '/callThirdPartyApi', 50 | }, 51 | Api: { 52 | List: '/manager/api/list', 53 | Add: '/manager/api/add', 54 | Delete: '/manager/api/info', 55 | Modify: '/manager/api/info', 56 | }, 57 | UserInfo: { 58 | Info: '/userinfo/user', 59 | Add: '/userinfo/user', 60 | Delete: '/userinfo/user', 61 | Put: '/userinfo/user', 62 | Login: '/userinfo/login', 63 | }, 64 | Map: { 65 | /** 66 | * post header token 加入活动 67 | * -------------------------------------- 68 | */ 69 | JoinPlace: '/map/joinplace', 70 | /** 71 | * post header token 添加活动起点 72 | * -------------------------------------- 73 | */ 74 | AddPlace: '/map/place', 75 | /** 76 | * get header token 获取我的活动点列表 77 | * -------------------------------------- 78 | */ 79 | MyPlaceList: '/map/placelist', 80 | /** 81 | * get header token 获取活动详情 82 | * ----------------------------------- 83 | */ 84 | JoinPlaceDetail: '/map/joinplacedetail', 85 | /** 86 | * put header token 更新当前的位置 87 | * ----------------------------------- 88 | */ 89 | UpdatePosition: '/map/place/join/detail', 90 | } 91 | } 92 | 93 | GetFormData(files) { 94 | const formData = new FormData(); 95 | formData.append('test1', 'test_1'); 96 | formData.append('test2', 'test_2'); 97 | formData.append('test3', 'test_3'); 98 | files.forEach((file) => { 99 | formData.append(file.name, file, file.name); 100 | }); 101 | return formData; 102 | } 103 | 104 | /** 105 | * Creates an instance of ApiClient. 106 | * @param {any} req 107 | * @memberof ApiClient 108 | */ 109 | constructor(req) { 110 | /** 111 | * 循环生成五个方法 112 | */ 113 | methods.forEach((method) => { 114 | this[method] = (path, condition) => { 115 | const { params, data, isFormData } = condition || { params: null, data: null, isFormData: false }; 116 | return new Promise((resolve, reject) => { 117 | const request = superagent[method](formatUrl(path)); 118 | const { token } = Utility.$GetContent(Utility.$ConstItem.UserInfo) || { token: null }; 119 | request.header.xiaotuni = 'liaohaibing_' + new Date().getTime(); 120 | request.header.token = token; 121 | if (params) { 122 | request.query(params); 123 | } 124 | 125 | if (req && req.get('cookie')) { 126 | request.set('cookie', req.getCookie()); 127 | } 128 | 129 | if (path === this.API.Common.FilesUpload) { 130 | request.send(this.GetFormData(data)); 131 | } else if (data) { 132 | if (!!isFormData) { 133 | const fd = new FormData(); 134 | Object.keys(data).forEach((field) => { 135 | fd.append(field, data[field]) 136 | }); 137 | request.send(fd); 138 | } else { 139 | request.send(data); 140 | } 141 | } 142 | const { HttpStatus } = Utility.$ConstItem.Events; 143 | /** 144 | * 错误处理及提示 145 | * 146 | * @param {any} err 147 | */ 148 | function __ProcessError(err, body, __req) { 149 | try { 150 | Utility.$LoadingHide(); 151 | const { code, msg } = body || { code: 400, msg: '处理错误' }; 152 | if (err.status) { 153 | if (HttpStatus[err.status]) { 154 | if (err.status === 400 && HttpStatus[__req.status]) { 155 | Utility.$Emit(HttpStatus[__req.status], { code: code || __req.status, msg: msg || err.message, body }); 156 | } else { 157 | Utility.$Emit(HttpStatus[err.status], { code: code || err.status, msg: msg || err.message, body }); 158 | } 159 | } else { 160 | Utility.$Emit(HttpStatus[400], { code: err.status, msg: err.message }); 161 | } 162 | } else if (!!err.crossDomain) { 163 | Utility.$ActionSheet('与服务器连接中断...'); 164 | } else if (err.message && err.message !== '') { 165 | Utility.$ActionSheet(err.message); 166 | } 167 | } catch (ex) { 168 | console.log(ex); 169 | } 170 | } 171 | 172 | const __PageTurning = (body) => { 173 | const { PageIndex, PageSize } = params || { PageSize: null, PageIndex: null }; 174 | if (PageIndex >= 0) { 175 | if (Array.isArray(body)) { 176 | const __Size = body.length; 177 | const Condition = Object.assign({}, params); 178 | Condition.IsNextData = __Size === PageSize ? true : false; 179 | Condition.PageIndex++; 180 | return { 181 | List: body, 182 | Condition 183 | }; 184 | } 185 | } 186 | return body; 187 | } 188 | 189 | function __SendRequest(_request) { 190 | _request.end((err, Response) => { 191 | const { body } = Response || { body: {} }; 192 | if (err) { 193 | __ProcessError(err, body, Response); 194 | reject(body); 195 | } else { 196 | if (!body) { 197 | Utility.$Emit(HttpStatus[Response.status], { status: Response.status, msg: '处理成功', Response }); 198 | } 199 | resolve(__PageTurning(body)); 200 | } 201 | }); 202 | } 203 | 204 | try { 205 | __SendRequest(request); 206 | } catch (ex) { 207 | console.log(ex); 208 | reject({ code: 500, msg: ex.message }) 209 | } 210 | }); 211 | } 212 | }); 213 | } 214 | empty() { 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/app/helpers/ClientMiddleware.ts: -------------------------------------------------------------------------------- 1 | export default function ClientMiddleware(client) { 2 | 3 | /** 4 | * 批处理操作 5 | * 6 | * @param {any} args 7 | * @returns 8 | */ 9 | const __BatchCallAPI = (args) => { 10 | const { commit, actions } = args; 11 | const { loading, fail, complete, list } = actions; 12 | const __APIList = []; 13 | list.forEach((item) => { 14 | const { promise } = item; 15 | __APIList.push(promise(client)); 16 | }); 17 | return new Promise((resolve, reject) => { 18 | Promise.all(__APIList) 19 | .then((results) => resolve(results), (err) => reject(err)) 20 | .catch((error) => reject(error)); 21 | }); 22 | }; 23 | 24 | /** 25 | * 方法调用 26 | * 27 | * @param {any} args 28 | * @returns 29 | */ 30 | const __CallMethod = (args) => { 31 | const { dispatch, commit, state, action, actions } = args; 32 | // 判断是否是批量调用接口 33 | if (actions) { 34 | return __BatchCallAPI(args); 35 | } 36 | if (typeof action === 'function') { 37 | return action(dispatch, state); 38 | } 39 | const { promise, type, ...rest } = action; 40 | 41 | return new Promise((resolve, reject) => { 42 | promise(client).then((result) => { 43 | resolve(result); 44 | }, (error) => { 45 | reject(error); 46 | }).catch((error) => error); 47 | }); 48 | }; 49 | return __CallMethod; 50 | } 51 | -------------------------------------------------------------------------------- /src/app/helpers/Core.ts: -------------------------------------------------------------------------------- 1 | // 访问接口 2 | import ApiClient from './ApiClient'; 3 | import ClientMiddleware from './ClientMiddleware'; 4 | export const Client = ClientMiddleware(new ApiClient(null)); -------------------------------------------------------------------------------- /src/app/manage/Core.ts: -------------------------------------------------------------------------------- 1 | export { Utility } from '../Common/Utility'; 2 | export { ServiceHelper } from '../service/index'; 3 | export { BaseComponent } from '../containers/base.component'; 4 | export { routeAnimation } from '../containers/app.animations'; 5 | -------------------------------------------------------------------------------- /src/app/manage/Index.ts: -------------------------------------------------------------------------------- 1 | import { Login } from './login/login'; 2 | import { Register } from './register/register'; 3 | import { UserList } from './userlist/userlist'; 4 | import { Dashboard, Address, Places, Contacts } from './dashboard/Index'; 5 | 6 | const __Router = { Address, ...Places, Contacts, Login, UserList, Register, Dashboard }; 7 | const __Keys = Object.keys(__Router); 8 | 9 | const __PageList = []; 10 | __Keys.forEach((key) => { 11 | __PageList.push(__Router[key]); 12 | }); 13 | 14 | export const ManagerRouter = __Router; 15 | export const ManagerPageComponentList = __PageList; -------------------------------------------------------------------------------- /src/app/manage/dashboard/Address/Address.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/manage/dashboard/Address/Address.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/manage/dashboard/Address/Address.scss -------------------------------------------------------------------------------- /src/app/manage/dashboard/Address/Address.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Utility, routeAnimation, BaseComponent } from '../../Core'; 3 | 4 | @Component({ 5 | moduleId: module.id, 6 | selector: 'app-manage-Dashboard-address', 7 | templateUrl: 'Address.html', 8 | styleUrls: ['./Address.scss'], 9 | animations: [routeAnimation], 10 | }) 11 | export class Address extends BaseComponent { 12 | 13 | constructor() { 14 | super(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/app/manage/dashboard/Contacts/Contacts.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/manage/dashboard/Contacts/Contacts.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/manage/dashboard/Contacts/Contacts.scss -------------------------------------------------------------------------------- /src/app/manage/dashboard/Contacts/Contacts.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Utility, routeAnimation, BaseComponent } from '../../Core'; 3 | 4 | @Component({ 5 | moduleId: module.id, 6 | selector: 'app-manage-Dashboard-contacts', 7 | templateUrl: 'Contacts.html', 8 | styleUrls: ['./Contacts.scss'], 9 | animations: [routeAnimation], 10 | }) 11 | export class Contacts extends BaseComponent { 12 | 13 | constructor() { 14 | super(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/app/manage/dashboard/Dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/manage/dashboard/Dashboard.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/manage/dashboard/Dashboard.scss -------------------------------------------------------------------------------- /src/app/manage/dashboard/Dashboard.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Utility, routeAnimation, BaseComponent } from '../Core'; 3 | 4 | @Component({ 5 | moduleId: module.id, 6 | selector: 'app-manage-Dashboard', 7 | templateUrl: 'Dashboard.html', 8 | styleUrls: ['./Dashboard.scss'], 9 | animations: [routeAnimation], 10 | }) 11 | export class Dashboard extends BaseComponent { 12 | 13 | constructor() { 14 | super(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/app/manage/dashboard/Index.ts: -------------------------------------------------------------------------------- 1 | export { Dashboard } from './Dashboard' 2 | export { Places } from './Place/Index' 3 | export { Contacts } from './Contacts/Contacts' 4 | export { Address } from './Address/Address' 5 | -------------------------------------------------------------------------------- /src/app/manage/dashboard/Place/Index.ts: -------------------------------------------------------------------------------- 1 | import { Place } from './Place'; 2 | import { PlaceList } from './PlaceList/PlaceList'; 3 | 4 | 5 | export const Places = { Place, PlaceList }; 6 | -------------------------------------------------------------------------------- /src/app/manage/dashboard/Place/Place.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/manage/dashboard/Place/Place.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/manage/dashboard/Place/Place.scss -------------------------------------------------------------------------------- /src/app/manage/dashboard/Place/Place.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Utility, routeAnimation, BaseComponent } from '../../Core'; 3 | 4 | @Component({ 5 | moduleId: module.id, 6 | selector: 'app-manage-Dashboard-place', 7 | templateUrl: 'Place.html', 8 | styleUrls: ['./Place.scss'], 9 | animations: [routeAnimation], 10 | }) 11 | export class Place extends BaseComponent { 12 | 13 | constructor() { 14 | super(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/app/manage/dashboard/Place/PlaceList/PlaceList.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/manage/dashboard/Place/PlaceList/PlaceList.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/app/manage/dashboard/Place/PlaceList/PlaceList.scss -------------------------------------------------------------------------------- /src/app/manage/dashboard/Place/PlaceList/PlaceList.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Utility, routeAnimation, BaseComponent } from '../../../Core'; 3 | 4 | @Component({ 5 | moduleId: module.id, 6 | selector: 'app-manage-Dashboard-place-list', 7 | templateUrl: 'PlaceList.html', 8 | styleUrls: ['./PlaceList.scss'], 9 | animations: [routeAnimation], 10 | }) 11 | export class PlaceList extends BaseComponent { 12 | 13 | constructor() { 14 | super(); 15 | } 16 | } -------------------------------------------------------------------------------- /src/app/manage/login/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
7 | 8 |
9 |
10 | 11 |
12 |
13 | 14 | 15 |
16 |
17 | 18 |
19 |
20 | 23 |
24 |
25 |
26 | 忘记密码 27 |
28 |
29 |
30 |
-------------------------------------------------------------------------------- /src/app/manage/login/login.scss: -------------------------------------------------------------------------------- 1 | .loginCss { 2 | padding: 10px; 3 | 4 | .ctrl { 5 | margin-top: 20vh; 6 | position: relative; 7 | 8 | input { 9 | border: 1px solid #f5f5f5; 10 | padding: 5px 10px; 11 | border-radius: 5px; 12 | flex: 1; 13 | font-size: 1rem; 14 | } 15 | 16 | .username { 17 | position: relative; 18 | display: flex; 19 | } 20 | 21 | .password { 22 | @extend .username; 23 | margin-top: 2rem; 24 | } 25 | 26 | .captcha { 27 | margin-top: 2rem; 28 | display: flex; 29 | align-items: center; 30 | } 31 | } 32 | 33 | .operator { 34 | display: flex; 35 | 36 | padding: 2rem; 37 | 38 | .btn { 39 | margin: 5px; 40 | flex: 1; 41 | text-align: center; 42 | padding: 5px 10px; 43 | 44 | >div { 45 | padding: 5px 10px; 46 | border: 1px solid #999; 47 | 48 | &:hover { 49 | border: 1px solid blue; 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/app/manage/login/login.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, Input } from '@angular/core'; 2 | import { Utility, ServiceHelper, routeAnimation, BaseComponent } from '../Core'; 3 | import * as CryptoJS from 'crypto-js'; 4 | 5 | @Component({ 6 | selector: 'xtn-manage-login', 7 | templateUrl: './login.html', 8 | styleUrls: ['./login.scss'], 9 | animations: [routeAnimation], // 页面切换动画 10 | providers: [ServiceHelper] // 注入一个service 11 | }) 12 | export class Login extends BaseComponent implements OnInit { 13 | public UserInfo: any; 14 | captchaUrl: string = "https://127.0.0.1:30081/webapi/apihelper/captchaCode"; 15 | /** 16 | * Creates an instance of Login. 17 | * @param {ServiceHelper} sHelper service用于接口调用等 18 | * @memberof Login 19 | */ 20 | constructor(private sHelper: ServiceHelper) { 21 | super(); 22 | this.UserInfo = { username: 'admin', password: 'admin@163.com' }; 23 | } 24 | 25 | ngOnInit() { 26 | } 27 | 28 | /** 29 | * 点击登录按钮 30 | * 31 | * @memberof Login 32 | */ 33 | submit() { 34 | const data = Object.assign({}, this.UserInfo); 35 | data.password = CryptoJS.MD5(data.password).toString(); 36 | this.sHelper.UserInfo.Login(data).then(() => { 37 | const { Params } = Utility.$GetContent(Utility.$ConstItem.UrlPathInfo) || { Params: {} }; 38 | const { IsGoBack } = Params || { IsGoBack: 0 }; 39 | if (!!Number(IsGoBack)) { 40 | Utility.$GoBack(); 41 | } else { 42 | Utility.$ToPage(Utility.$ConstItem.UrlItem.ManagerDashboard, {}); 43 | } 44 | }, () => { 45 | 46 | }); 47 | } 48 | 49 | onClickUpdateCaptcha() { 50 | this.captchaUrl = "https://127.0.0.1:30081/webapi/apihelper/captchaCode?times" + new Date().getTime(); 51 | } 52 | 53 | forgetPassword() { 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/app/manage/register/register.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 |
6 |
7 | 8 |
9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
29 |
{{item.type}}
30 |
{{item.name}}
31 |
{{item.size}}
32 | 33 |
34 |
35 | 36 | 39 |
40 |
41 | 42 |
确定
43 |
44 |
-------------------------------------------------------------------------------- /src/app/manage/register/register.scss: -------------------------------------------------------------------------------- 1 | .registerCss { 2 | padding: 20px; 3 | 4 | input { 5 | padding: 5px 10px; // width: 100%; 6 | flex: 1; 7 | } 8 | .title { 9 | text-align: center; 10 | font-size: 20px; 11 | margin-bottom: 20px; 12 | } 13 | 14 | .row { 15 | margin-bottom: 5px; 16 | display: flex; 17 | } 18 | .userHeader { 19 | .selectHeader { 20 | padding: 10px; 21 | } 22 | .header { 23 | margin: 20px; 24 | width: 100%; 25 | height: 30vh; 26 | text-align: center; 27 | >img { 28 | height: 100%; 29 | } 30 | } 31 | } 32 | .file { 33 | @extend .row; 34 | .name { 35 | flex: 1; 36 | margin: 0px 10px; 37 | } 38 | } 39 | .filelist { 40 | position: relative; 41 | input { 42 | margin-top: 5px; 43 | width: 100%; 44 | } 45 | } 46 | .btn { 47 | cursor: default; 48 | justify-content: center; 49 | display: flex; 50 | margin-top: 20px; 51 | >div { 52 | padding: 5px 20px; 53 | border: 1px solid #999; 54 | border-radius: 5px; 55 | 56 | &:hover { 57 | background: blue; 58 | color: #fff; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/app/manage/register/register.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, Input } from '@angular/core'; 2 | import { Utility, ServiceHelper, routeAnimation, BaseComponent } from '../Core'; 3 | import { DomSanitizer } from '@angular/platform-browser'; 4 | import * as CryptoJS from 'crypto-js'; 5 | 6 | @Component({ 7 | selector: 'xtn-manage-register', 8 | templateUrl: './register.html', 9 | animations: [routeAnimation], 10 | styleUrls: ['./register.scss'], 11 | providers: [ServiceHelper] 12 | }) 13 | export class Register extends BaseComponent implements OnInit { 14 | public UserInfo: any; 15 | constructor(private sHelper: ServiceHelper, private sanitizer: DomSanitizer) { 16 | super(); 17 | this.UserInfo = { UserName: 1, Password: 1, ConfromPassword: 1, Tel: '12142141', Address: 'address' }; 18 | } 19 | 20 | ngOnInit() { 21 | } 22 | 23 | __ClickRegister() { 24 | const data = Object.assign({}, this.UserInfo); 25 | data.Password = CryptoJS.MD5(this.UserInfo.Password).toString(); 26 | const __self = this; 27 | this.sHelper.UserInfo.AddUser(data).then(() => { 28 | }); 29 | } 30 | 31 | HeadPortrait: any; 32 | onChangeHeadPortrait(event, field) { 33 | const file = event.currentTarget.files[0]; 34 | this.UserInfo[field] = file; 35 | this.HeadPortrait = this.sanitizer.bypassSecurityTrustUrl(window.URL.createObjectURL(file)); 36 | } 37 | 38 | onChangeFileList(event, field) { 39 | if (!this.UserInfo.FileList) { 40 | this.UserInfo.FileList = []; 41 | } 42 | const file = event.currentTarget.files[0]; 43 | this.UserInfo.FileList.push(file); 44 | } 45 | 46 | btnDeleteSelectDelete(index) { 47 | this.UserInfo.FileList.splice(index, 1); 48 | } 49 | btnSubmit() { 50 | const data = Object.assign({}, this.UserInfo); 51 | data.Password = CryptoJS.MD5(this.UserInfo.Password).toString(); 52 | const __self = this; 53 | this.sHelper.UserInfo.Register(data).then(() => { 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/app/manage/userlist/userlist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |
全选
7 |
ID
8 |
名称
9 |
电话
10 |
11 |
删除
12 |
13 |
14 |
修改
15 |
16 |
17 | 18 |
19 |
20 |
21 |
22 |
{{item.id}}
23 |
{{item.username}}
24 |
{{item.tel}}
25 |
26 |
删除
27 |
28 |
29 |
修改
30 |
31 |
32 | 33 |
34 |
-------------------------------------------------------------------------------- /src/app/manage/userlist/userlist.scss: -------------------------------------------------------------------------------- 1 | .userlistCss { 2 | padding: 5px; 3 | font-size: 12px; 4 | 5 | .users { 6 | // border: 1px solid #f5f5f5; 7 | .row { 8 | border: 1px solid #f5f5f5; 9 | display: flex; 10 | align-items: center; 11 | .name { 12 | flex: 1; 13 | padding: 0px 5px; 14 | white-space: nowrap; 15 | text-overflow: ellipsis; 16 | overflow: hidden; 17 | } 18 | 19 | .btn { 20 | padding: 5px; 21 | >div { 22 | padding: 2px 5px; 23 | border: 1px solid #999; 24 | border-radius: 5px; 25 | 26 | &:hover { 27 | background: blue; 28 | color: #fff; 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/app/manage/userlist/userlist.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, Input, AfterViewInit } from '@angular/core'; 2 | import { Utility, ServiceHelper, BaseComponent, routeAnimation } from '../Core'; 3 | import * as CryptoJS from 'crypto-js'; 4 | 5 | @Component({ 6 | selector: 'xtn-manage-userlist', 7 | templateUrl: './userlist.html', 8 | styleUrls: ['./userlist.scss'], 9 | animations: [routeAnimation], 10 | providers: [ServiceHelper] 11 | }) 12 | export class UserList extends BaseComponent implements OnInit, AfterViewInit { 13 | public UserInfo: any; 14 | public userList: any; 15 | constructor(private sHelper: ServiceHelper) { 16 | super(); 17 | this.UserInfo = {}; 18 | } 19 | 20 | ngOnInit() { 21 | } 22 | 23 | ngAfterViewInit(): void { 24 | const c = { pageIndex: 0, pageSize: 15 }; 25 | const __self = this; 26 | this.sHelper.UserInfo.Userlist(c).then(() => { 27 | __self.userList = __self.sHelper.UserInfo.Users; 28 | }, () => { }); 29 | } 30 | 31 | __ClickDelete(item) { 32 | this.sHelper.UserInfo.DeleteUser(item).then(() => { }); 33 | } 34 | 35 | __ClickModify(item) { 36 | console.log(item); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/app/manageapi/Core.ts: -------------------------------------------------------------------------------- 1 | export { Utility } from '../Common/Utility'; 2 | export { ServiceHelper } from '../service/index'; 3 | -------------------------------------------------------------------------------- /src/app/manageapi/Index.ts: -------------------------------------------------------------------------------- 1 | import { ApiList } from './apilist/apilist'; 2 | 3 | 4 | const __Router = { ApiList }; 5 | const __Keys = Object.keys(__Router); 6 | 7 | const __PageList = []; 8 | __Keys.forEach((key) => { 9 | __PageList.push(__Router[key]); 10 | }); 11 | 12 | export const ManagerApiRouter = __Router; 13 | export const ManagerApiPageComponentList = __PageList; -------------------------------------------------------------------------------- /src/app/manageapi/apilist/apilist.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Token信息里的字段分别为:tokenUserId, deadline, tokenId 4 |
5 |
6 |
7 |
Id
8 |
类型
9 |
类型
10 |
状态
11 |
接口地址
12 |
描述
13 |
操作
14 |
15 |
16 |
17 |
{{item.Id}}
18 |
{{item.Method}}
19 |
{{item.MethodCn}}
20 |
{{item.StatusCn}}
21 |
{{item.PathName}}
22 |
{{item.Bewrite}}
23 |
24 | {{ CurrentItem && CurrentItem.Id === item.Id ?'收起' :'展开' }} 25 |
26 |
27 |
28 | 30 |
31 |
32 | 33 |
34 |
35 | 36 |
37 |
38 |
39 | 添加接口 40 |
41 |
42 |
43 |
44 | 保存接口 45 |
46 |
47 |
48 |
49 | 刷新接口 50 |
51 |
52 |
53 |
54 |
-------------------------------------------------------------------------------- /src/app/manageapi/apilist/apilist.scss: -------------------------------------------------------------------------------- 1 | .apiListCss { 2 | font-size: 12px; 3 | .token { 4 | font-size: 14px; 5 | color: red; 6 | text-align: center 7 | } 8 | .apiInfo { 9 | .api { 10 | display: flex; 11 | border-top: 1px solid #f5f5f5; // padding: 5px 0px; 12 | >div { 13 | border-right: 1px solid #f5f5f5; 14 | padding: 5px 0; 15 | } 16 | 17 | &:hover { 18 | // border: 1px solid #f5f5f5; 19 | background: #f5f5f5; 20 | } 21 | 22 | .method { 23 | width: 35px; 24 | padding: 5px; 25 | } 26 | .methodCn { 27 | @extend .method; 28 | } 29 | .__overflow { 30 | 31 | overflow: hidden; 32 | text-overflow: ellipsis; 33 | white-space: nowrap; 34 | } 35 | .bewrite { 36 | flex: 1; 37 | padding: 5px; 38 | @extend .__overflow; 39 | } 40 | 41 | .statu { 42 | padding: 5px 15px; 43 | } 44 | .path { 45 | padding-left: 5px; 46 | @extend .__overflow; 47 | } 48 | 49 | .operator { 50 | padding: 5px 10px; 51 | } 52 | } 53 | 54 | .item { 55 | border: 1px solid #f5f5f5; 56 | } 57 | margin-right: 10px; 58 | } 59 | 60 | .addApi { 61 | border: 1px solid #f5f5f5; 62 | 63 | .btns { 64 | display: flex; 65 | justify-content: center; // padding: 20px; 66 | .btn { 67 | margin: 5px; 68 | 69 | >div { 70 | border: 1px solid #f5f5f5; 71 | border-radius: 5px; 72 | padding: 5px 20px; 73 | font-size: 14px; 74 | 75 | &:hover { 76 | background: blue; 77 | color: #fff; 78 | } 79 | } 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/app/manageapi/apilist/apilist.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, Input } from '@angular/core'; 2 | import { animate, state, style, transition, trigger } from '@angular/animations'; 3 | import { Utility, ServiceHelper } from '../Core'; 4 | import * as CryptoJS from 'crypto-js'; 5 | 6 | @Component({ 7 | selector: 'xtn-manage-apilist', 8 | templateUrl: './apilist.html', 9 | styleUrls: ['./apilist.scss'], 10 | providers: [ServiceHelper], 11 | animations: [trigger( 12 | 'openClose', 13 | [ 14 | state('collapsed, void', style({ height: '0px', color: 'maroon', borderColor: 'maroon' })), 15 | state('expanded', style({ height: '*', borderColor: 'green', color: 'green' })), 16 | transition( 17 | 'collapsed <=> expanded', [animate(500, style({ height: '250px' })), animate(500)]) 18 | ])] 19 | }) 20 | export class ApiList implements OnInit { 21 | public ApiList: any; 22 | public NewApiInfo: any = { RuleInfo: { rules: [] } }; 23 | public CurrentItem: any; 24 | public isAddNewApiInfo: boolean = false; 25 | stateExpression: string = 'collapsed'; 26 | 27 | constructor(private sHelper: ServiceHelper) { 28 | } 29 | 30 | ngOnInit() { 31 | const __self = this; 32 | this.sHelper.ApiManager.List().then(() => { 33 | __self.ApiList = __self.sHelper.ApiManager.ApiList; 34 | // const { ApiList } = __self; 35 | // if (Array.isArray(ApiList)) { 36 | // __self.CurrentItem = ApiList[ApiList.length - 1]; 37 | // } 38 | }, (err) => { 39 | }); 40 | } 41 | 42 | onClickExpand(item) { 43 | if (this.CurrentItem === item) { 44 | this.CurrentItem = null; 45 | } else { 46 | this.CurrentItem = item; 47 | } 48 | } 49 | 50 | onClickRefresh() { 51 | this.ngOnInit(); 52 | } 53 | 54 | btnClickAdd() { 55 | this.isAddNewApiInfo = !this.isAddNewApiInfo; 56 | } 57 | 58 | btnClickSave() { 59 | this.NewApiInfo.Id = -1; 60 | this.sHelper.ApiManager.AddApi(this.NewApiInfo).then(() => { 61 | 62 | }, () => { }); 63 | } 64 | 65 | onSaveRule(rule) { 66 | this.sHelper.ApiManager.AddApi(rule).then((data) => { 67 | Utility.$ShowMessage('接口列表', '添加或修改成功。'); 68 | }, (ee) => { 69 | }); 70 | } 71 | 72 | onDeleteRule(rule) { 73 | this.sHelper.ApiManager.DeleteById(rule); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/app/service/ApiManager.ts: -------------------------------------------------------------------------------- 1 | export class ApiManagerService { 2 | private ApiClient: any; 3 | public ApiList: any; 4 | 5 | constructor(private client) { 6 | this.ApiClient = client; 7 | } 8 | List(): Promise { 9 | const __self = this; 10 | const options = { 11 | action: { 12 | promise: (client) => client.get(client.API.Api.List, { params: {} }), 13 | types: ['Loading', 'Success', 'Fail'] 14 | }, 15 | }; 16 | return this.ApiClient(options).then((data) => { 17 | __self.ApiList = data; 18 | if (Array.isArray(__self.ApiList)) { 19 | __self.ApiList.forEach(row => { 20 | const { Content } = row; 21 | try { 22 | row.RuleInfo = JSON.parse(Content); 23 | } catch (ex) { 24 | console.log(ex); 25 | } 26 | }); 27 | } 28 | return data; 29 | }); 30 | } 31 | 32 | AddApi(Info: object): Promise { 33 | const __self = this; 34 | return new Promise((resolve, reject) => { 35 | const options = { action: { types: ['Loading', 'Success', 'Fail'], promise: (client) => client.post(client.API.Api.Add, { params: {}, data: Info }) } }; 36 | __self.ApiClient(options).then((data) => { 37 | const { code, msg, Id } = data; 38 | if (code && msg) { 39 | // update 40 | } else { // insert 41 | const _find = __self.ApiList.filter((row) => row.Id === Id); 42 | if (_find.length > 0) { 43 | // _find[0].RuleInfo = JSON.parse(data.Content); 44 | } else { 45 | data.RuleInfo = JSON.parse(data.Content); 46 | __self.ApiList.push(data); 47 | } 48 | } 49 | resolve(data); 50 | }, (ee) => { 51 | reject(ee); 52 | }); 53 | }); 54 | } 55 | 56 | Modify(Info: object): Promise { 57 | const __self = this; 58 | const options = { 59 | action: { 60 | promise: (client) => client.put(client.API.Api.Modify, { params: {}, data: Info }), 61 | types: ['Loading', 'Success', 'Fail'] 62 | }, 63 | }; 64 | return this.ApiClient(options).then((data) => { 65 | return data; 66 | }); 67 | } 68 | 69 | DeleteById(rule) { 70 | const { Id } = rule; 71 | const __self = this; 72 | const options = { 73 | action: { 74 | promise: (client) => client.del(client.API.Api.Delete, { params: {}, data: { Id } }), 75 | types: ['Loading', 'Success', 'Fail'] 76 | }, 77 | }; 78 | return this.ApiClient(options).then((data) => { 79 | const { ApiList } = __self; 80 | for (let i = 0; i < ApiList.length; i++) { 81 | if (ApiList[i].Id === Id) { 82 | ApiList.splice(i, 1); 83 | break; 84 | } 85 | } 86 | return data; 87 | }); 88 | } 89 | } -------------------------------------------------------------------------------- /src/app/service/BaiduMapService.ts: -------------------------------------------------------------------------------- 1 | export class BaiduMapService { 2 | 3 | private ApiClient: any; 4 | Status: any = { 5 | BMAP_STATUS_SUCCESS: { name: '检索成功', value: 0 }, 6 | BMAP_STATUS_CITY_LIST: { name: '城市列表', value: 1 }, 7 | BMAP_STATUS_UNKNOWN_LOCATION: { name: '位置结果未知', value: 2 }, 8 | BMAP_STATUS_UNKNOWN_ROUTE: { name: '导航结果未知', value: 3 }, 9 | BMAP_STATUS_INVALID_KEY: { name: '非法密钥', value: 4 }, 10 | BMAP_STATUS_INVALID_REQUEST: { name: '非法请求', value: 5 }, 11 | BMAP_STATUS_PERMISSION_DENIED: { name: '没有权限', value: 6 }, 12 | BMAP_STATUS_SERVICE_UNAVAILABLE: { name: '服务不可用', value: 7 }, 13 | BMAP_STATUS_TIMEOUT: { name: '超时', value: 8 }, 14 | } 15 | /** 16 | * 当前要查看的活动信息 17 | * 18 | * @type {*} 19 | * @memberof BaiduMapService 20 | */ 21 | public CurrentPlaceInfo: any; 22 | /** 23 | * 我的活动列表 24 | * 25 | * @type {*} 26 | * @memberof BaiduMapService 27 | */ 28 | public PlaceListInfo: any; 29 | 30 | /** 31 | * 加入活动的人员列表 32 | * 33 | * @type {Array} 34 | * @memberof BaiduMapService 35 | */ 36 | public JoinPlaceList: Array; 37 | 38 | constructor(private client) { 39 | this.ApiClient = client; 40 | } 41 | 42 | AddPlace(placeInfo): Promise { 43 | const OldPI = JSON.parse(JSON.stringify(placeInfo)); 44 | OldPI.BeginDate = OldPI.BeginTime; 45 | OldPI.EndDate = OldPI.EndTime; 46 | OldPI.BeginDate = parseInt(OldPI.BeginDate, 0); 47 | OldPI.EndDate = parseInt(OldPI.EndDate, 0); 48 | if (!OldPI.Bewrite || OldPI.Bewrite === '') { 49 | OldPI.Bewrite = OldPI.Address; 50 | } 51 | delete OldPI.BeginTime; 52 | delete OldPI.EndTime; 53 | 54 | const __self = this; 55 | const options = { 56 | action: { 57 | types: ['Loading', 'Success', 'Fail'], 58 | promise: (client) => client.post(client.API.Map.AddPlace, { data: OldPI }), 59 | }, 60 | }; 61 | return this.ApiClient(options).then((data) => { 62 | return data; 63 | }); 64 | } 65 | 66 | MyPlaceList(Condition: any): Promise { 67 | const { PageSize, PageIndex } = Condition; 68 | const __self = this; 69 | const options = { 70 | action: { 71 | types: ['Loading', 'Success', 'Fail'], promise: (client) => client.get(client.API.Map.MyPlaceList, { params: Condition || {} }), 72 | }, 73 | }; 74 | 75 | return this.ApiClient(options).then((data) => { 76 | const { List, Condition } = data; 77 | const { PlaceListInfo } = __self; 78 | if (!__self.PlaceListInfo || PageIndex === 0) { 79 | __self.PlaceListInfo = data; 80 | } else { 81 | __self.PlaceListInfo.List = __self.PlaceListInfo.List.concat(List) 82 | __self.PlaceListInfo.Condition = Condition; 83 | } 84 | 85 | return data; 86 | }); 87 | } 88 | 89 | JoinPlace(InviteCode): Promise { 90 | const __self = this; 91 | const options = { 92 | action: { 93 | types: ['Loading', 'Success', 'Fail'], 94 | promise: (client) => client.post(client.API.Map.JoinPlace, { data: { InviteCode } }), 95 | }, 96 | }; 97 | return this.ApiClient(options).then((data) => { 98 | return data; 99 | }); 100 | } 101 | 102 | JoinPlaceDetail(PlaceId): Promise { 103 | const __self = this; 104 | const options = { 105 | action: { 106 | promise: (client) => client.get(client.API.Map.JoinPlaceDetail, { params: { PlaceId } }), 107 | }, 108 | }; 109 | return this.ApiClient(options).then((data) => { 110 | __self.JoinPlaceList = data; 111 | return data; 112 | }); 113 | 114 | } 115 | } -------------------------------------------------------------------------------- /src/app/service/CommonService.ts: -------------------------------------------------------------------------------- 1 | export class CommonService { 2 | 3 | public CurrentRouterQueryParams: any; 4 | public CurrentRouterPathInfo: any; 5 | private ApiClient: any; 6 | AreaInfo: any; 7 | CaptchaInfo: any; 8 | 9 | constructor(private client) { 10 | this.ApiClient = client; 11 | } 12 | 13 | GetArea(condition): Promise { 14 | const __self = this; 15 | const options = { 16 | action: { 17 | promise: (client) => client.get(client.API.Common.Area, { params: condition || { PageIndex: 0, PageSize: 10 } }), 18 | types: ['Loading', 'Success', 'Fail'] 19 | }, 20 | }; 21 | const { PageIndex, PageSize } = condition || { PageIndex: 0, PageSize: 10 }; 22 | return this.ApiClient(options).then((data) => { 23 | const { List, Condition } = data; 24 | if (PageIndex === 0) { 25 | __self.AreaInfo = data; 26 | } else { 27 | __self.AreaInfo.List = __self.AreaInfo.List.concat(List) 28 | __self.AreaInfo.Condition = Condition; 29 | } 30 | return data; 31 | }); 32 | } 33 | 34 | GetCaptcha(): Promise { 35 | const self = this; 36 | const options = { action: { promise: (client) => client.get(client.API.Common.Captcha, {}) } }; 37 | return this.ApiClient(options).then((success) => { 38 | self.CaptchaInfo = success; 39 | return success; 40 | }); 41 | } 42 | 43 | FileUpload(file): Promise { 44 | const self = this; 45 | const options = { action: { promise: (client) => client.post(client.API.Common.FileUpload, { data: file }) } }; 46 | return this.ApiClient(options).then((success) => { 47 | self.CaptchaInfo = success; 48 | return success; 49 | }); 50 | } 51 | 52 | FilesUpload(files): Promise { 53 | const self = this; 54 | const options = { action: { promise: (client) => client.post(client.API.Common.FilesUpload, { data: files }) } }; 55 | return this.ApiClient(options).then((success) => { 56 | self.CaptchaInfo = success; 57 | return success; 58 | }); 59 | } 60 | 61 | 62 | CallOtherApi() { 63 | const self = this; 64 | const options = { action: { promise: (client) => client.post(client.API.Common.CallThirdPartyApi, { data: { id: 1, name: '1234' } }) } }; 65 | return this.ApiClient(options).then((success) => { 66 | self.CaptchaInfo = success; 67 | return success; 68 | }); 69 | } 70 | } -------------------------------------------------------------------------------- /src/app/service/Core.ts: -------------------------------------------------------------------------------- 1 | export { Client } from '../helpers/Core'; 2 | export { Utility } from '../Common/Utility' -------------------------------------------------------------------------------- /src/app/service/Demo.ts: -------------------------------------------------------------------------------- 1 | import { Client } from './Core'; 2 | 3 | export class DemoService { 4 | private __Client: any; 5 | 6 | constructor(private client) { 7 | this.__Client = client; 8 | } 9 | 10 | public UserInfo(methodType) { 11 | const __self = this; 12 | const options = { 13 | action: { 14 | promise: (client) => client[methodType](client.API.UserInfo.Info, { params: {} }), 15 | types: ['Loading', 'Success', 'Fail'] 16 | }, 17 | }; 18 | return this.__Client(options).then((data) => { 19 | console.log(data); 20 | return data; 21 | }); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/app/service/ServiceHelper.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Client } from './Core'; 3 | import { ApiManagerService } from './ApiManager'; 4 | import { DemoService } from './Demo'; 5 | import { UserInfoService } from './UserInfo'; 6 | import { CommonService } from './CommonService'; 7 | import { BaiduMapService } from './BaiduMapService'; 8 | 9 | @Injectable() 10 | export class ServiceHelper { 11 | public ApiManager: ApiManagerService; 12 | public DemoService: DemoService; 13 | public UserInfo: UserInfoService; 14 | public Common: CommonService; 15 | public BaiduMap: BaiduMapService; 16 | constructor() { 17 | this.ApiManager = new ApiManagerService(Client); 18 | this.UserInfo = new UserInfoService(Client); 19 | this.DemoService = new DemoService(Client); 20 | this.BaiduMap = new BaiduMapService(Client); 21 | this.Common = new CommonService(Client); 22 | } 23 | } -------------------------------------------------------------------------------- /src/app/service/UserInfo.ts: -------------------------------------------------------------------------------- 1 | import { Utility } from './Core'; 2 | 3 | export class UserInfoService { 4 | public UserInfo: any; 5 | public Users: any[]; 6 | 7 | constructor(private Client) { 8 | } 9 | 10 | /** 11 | * 用户登录 12 | * 13 | * @param {*} obj 14 | * @returns {Promise} 15 | * @memberof UserInfoService 16 | */ 17 | Login(obj: any): Promise { 18 | const __List = { actions: { list: [], loading: 'Load', fail: 'Fail', complete: 'Complete' } }; 19 | __List.actions.list.push({ 20 | StateName: 'StateName', Condition: obj, 21 | promise: (client) => client.post(client.API.UserInfo.Login, { data: obj, isFormData: false }), 22 | }); 23 | const __self = this; 24 | return this.Client(__List).then((result) => { 25 | __self.UserInfo = result && result[0] ? result[0] : []; 26 | // 将token保存下来。 27 | Utility.$SetContent(Utility.$ConstItem.UserInfo, __self.UserInfo, true); 28 | return result; 29 | }); 30 | } 31 | 32 | /** 33 | * 添加用户 34 | * 35 | * @param {*} obj 36 | * @returns {Promise} 37 | * @memberof UserInfoService 38 | */ 39 | AddUser(obj: any): Promise { 40 | const __List = { actions: { list: [], loading: 'Load', fail: 'Fail', complete: 'Complete' } }; 41 | __List.actions.list.push({ 42 | StateName: 'StateName', Condition: obj, 43 | promise: (client) => client.post(client.API.Common.AddUser, { data: obj, isFormData: true }), 44 | }); 45 | const __self = this; 46 | return this.Client(__List).then((result) => { 47 | __self.UserInfo = result && result[0] ? result[0] : []; 48 | return result; 49 | }); 50 | } 51 | 52 | Register(userInfo): Promise { 53 | const fd = new FormData(); 54 | const nValue = Object.assign({}, userInfo); 55 | delete nValue.FileList; 56 | userInfo.FileList.forEach((file) => { 57 | fd.append('fileCollection', file, file.name); 58 | }); 59 | userInfo.fList = fd; 60 | 61 | Object.keys(nValue).forEach((key) => { 62 | fd.append(key, nValue[key]); 63 | }); 64 | 65 | const action = { 66 | StateName: 'StateName', types: ['Loading', 'Success', 'Fail'], Condition: userInfo, 67 | promise: (client) => client.post(client.API.Common.AddUser, { data: fd }), 68 | }; 69 | const __self = this; 70 | return this.Client({ action }).then((result) => { 71 | 72 | return result; 73 | }); 74 | } 75 | 76 | /** 77 | * 用户列表 78 | * 79 | * @param {*} cnd 80 | * @returns {Promise} 81 | * @memberof UserInfoService 82 | */ 83 | Userlist(cnd: any): Promise { 84 | const __List = { actions: { list: [], loading: 'Load', fail: 'Fail', complete: 'Complete' } }; 85 | __List.actions.list.push({ 86 | StateName: 'StateName', Condition: cnd, 87 | promise: (client) => client.get(client.API.Common.Userlist, { params: cnd }), 88 | }); 89 | const __self = this; 90 | return this.Client(__List).then((result) => { 91 | __self.Users = result && result[0] ? result[0] : []; 92 | return result && result[0] ? result[0] : []; 93 | }); 94 | } 95 | 96 | /** 97 | * 删除用户操作 98 | * 99 | * @param {*} item 100 | * @returns {Promise} 101 | * @memberof UserInfoService 102 | */ 103 | DeleteUser(item: any): Promise { 104 | const action = { 105 | StateName: 'StateName', types: ['Loading', 'Success', 'Fail'], Condition: item, 106 | promise: (client) => client.del(client.API.Common.DeleteUser, { params: { id: item.id } }), 107 | }; 108 | const __self = this; 109 | return this.Client({ action }).then((result) => { 110 | for (let i = 0; i < __self.Users.length; i++) { 111 | const row = __self.Users[i]; 112 | if (row.id === item.id) { 113 | __self.Users.splice(i, 1); 114 | break; 115 | } 116 | } 117 | return result; 118 | }); 119 | } 120 | } -------------------------------------------------------------------------------- /src/app/service/index.ts: -------------------------------------------------------------------------------- 1 | export { ServiceHelper } from './ServiceHelper'; -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/img/car-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/assets/img/car-icon.png -------------------------------------------------------------------------------- /src/assets/img/person-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/assets/img/person-icon.png -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaotuni/angular-map-http2/cbdf739b76d5179c28f5c6cec65c6e92be3fcf2a/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TravelTogether 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | Loading... 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | import { AppModule } from './app/app.module'; 4 | import { environment } from './environments/environment'; 5 | 6 | if (environment.production) { 7 | console.log('-----enableProdMode----'); 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule); 12 | -------------------------------------------------------------------------------- /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/set'; 35 | 36 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 37 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 38 | 39 | /** IE10 and IE11 requires the following to support `@angular/animation`. */ 40 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 41 | 42 | 43 | /** Evergreen browsers require these. **/ 44 | import 'core-js/es6/reflect'; 45 | import 'core-js/es7/reflect'; 46 | 47 | 48 | /** ALL Firefox browsers require the following to support `@angular/animation`. **/ 49 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 50 | 51 | 52 | 53 | /*************************************************************************************************** 54 | * Zone JS is required by Angular itself. 55 | */ 56 | import 'zone.js/dist/zone'; // Included with Angular CLI. 57 | 58 | 59 | 60 | /*************************************************************************************************** 61 | * APPLICATION IMPORTS 62 | */ 63 | 64 | /** 65 | * Date, currency, decimal and percent pipes. 66 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 67 | */ 68 | // import 'intl'; // Run `npm install --save intl`. 69 | /** 70 | * Need to import at least one locale-data with intl. 71 | */ 72 | // import 'intl/locale-data/jsonp/en'; 73 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | body { 4 | margin: 0; 5 | } 6 | 7 | // .btns { 8 | // display: flex; 9 | // } 10 | 11 | // .btns .btn { 12 | // margin: 0 5px; 13 | // } 14 | 15 | // .btns .btn > div { 16 | // padding: 5px 10px; 17 | // border: 1px solid #f5f5f5; 18 | // border-radius: 5px; 19 | // } 20 | 21 | // .btns .btn > div:hover { 22 | // background: #999; 23 | // color: #fff; 24 | // } 25 | 26 | // .btns .btn-right { 27 | // justify-content: flex-end; 28 | // } 29 | 30 | .btns { 31 | display: flex; 32 | 33 | .btn { 34 | margin: 0 5px; 35 | 36 | > div { 37 | padding: 5px 10px; 38 | border: 1px solid #f5f5f5; 39 | border-radius: 5px; 40 | 41 | &:hover { 42 | background: #999; 43 | color: #fff; 44 | } 45 | } 46 | } 47 | 48 | .btn-right { 49 | justify-content: flex-end; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /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 var __karma__: any; 17 | declare var 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 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "es2015", 6 | "baseUrl": "", 7 | "types": [] 8 | }, 9 | "exclude": [ 10 | "test.ts", 11 | "**/*.spec.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "baseUrl": "", 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/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /temp.txt: -------------------------------------------------------------------------------- 1 | update sys_rule set content = ' 2 | { 3 | "rules":[ 4 | { 5 | "sql":"select * from xtn_userinfo where username = \':username\' and password = \':password\'", 6 | "id":1, "name":"admininfo", "type":"query", "isRows":false 7 | }, 8 | { 9 | "sql":"select count(1) total, sex,cityname,age from xtn_userinfo where id = :id_judge", 10 | "id":100,"type":"query","isRows":false,"name":"judgeInfo_100","isMergeOption":true 11 | }, 12 | { 13 | "id":10, 14 | "sql":"", 15 | "type":"judge", 16 | "judgeInfo":{ 17 | "strByEval1":"(\':sex\' !== \'男\' && \':cityname\' == \'北京\' ) || (:age > 30 && \':cityname\' !== \'北京\')", 18 | "strByThis":"if((this.sex === \'男\' && this.cityname == \'上海\' ) || (this.age > 30 && this.cityname !== \'北京\')){return true;}return false;", 19 | "failMsg":"用户存在", 20 | "chilrenRules":[ 21 | { 22 | "sql":"select * from xtn_userinfo where sex = \':sex\'", 23 | "id":11,"name":"peoples_sex","type":"query","isRows":true 24 | }, 25 | { 26 | "id":12,"name":"peoples_sex_city","type":"query","isRows":true, 27 | "sql":"select * from xtn_userinfo where sex = \':sex\' and cityname = \':cityname\' " 28 | } 29 | ] 30 | } 31 | }, 32 | { 33 | "sql":"select * from xtn_userinfo where id> :id", 34 | "id":2, "name":"userlist", "type":"query", "isRows":true 35 | }, 36 | { "id":3, "type":"beginTran" }, 37 | { 38 | "sql":"update xtn_userinfo t set t.tel=\':tel\' where t.id = :id1", 39 | "id":4, "name":"update_info", "type":"update", "isRows":false 40 | }, 41 | { 42 | "sql":"select * from xtn_userinfo where id = :id1", 43 | "id":5, "name":"id1_info","type":"query", "isRows":false 44 | }, 45 | { 46 | "sql":"insert into xtn_userinfo(username,password,tel,address) values(uuid_short(),md5(now()),\':tel\',\'哈哈\');", 47 | "id":6, "name":"InsertNo", "type":"insert" 48 | }, 49 | { 50 | "sql":"select * from xtn_userinfo t where t.id = :InsertNo", 51 | "id":7,"name":"insert_result11", "type":"query", "isRows":false 52 | }, 53 | { 54 | "sql":"select count(1) total from xtn_userinfo ", 55 | "id":9, "name":"insert_total1", "type":"query", "isRows":false 56 | }, 57 | { 58 | "sql":"delete from xtn_userinfo where id = :InsertNo - 5", 59 | "id":10,"name":"delete_result", "type":"delete" 60 | }, 61 | { "id":11, "type":"commit" }, 62 | { 63 | "sql":"select count(1) total from xtn_userinfo ", 64 | "id":13,"name":"insert_total2", "type":"query", "isRows":false 65 | } 66 | ], 67 | "fields":"username,password,id,tel,id1,id_judge", 68 | "result":1 69 | } 70 | ' 71 | where id = 1 72 | 73 | 74 | 75 | 76 | ------------------- 77 | CREATE TABLE `xtn_sys_file` ( 78 | `Id` int(11) NOT NULL AUTO_INCREMENT, 79 | `FileName` varchar(150) DEFAULT NULL COMMENT '文件名称', 80 | `FilePath` varchar(200) DEFAULT NULL COMMENT '文件路径', 81 | `Status` tinyint(1) DEFAULT '1', 82 | `CreateTime` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 83 | PRIMARY KEY (`Id`) 84 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='文件系统表'; 85 | 86 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/out-tsc", 5 | "baseUrl": "src", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "moduleResolution": "node", 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "target": "es5", 12 | "typeRoots": [ 13 | "node_modules/@types" 14 | ], 15 | "lib": [ 16 | "es2016", 17 | "dom" 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "callable-types": true, 7 | "class-name": true, 8 | "comment-format": [ 9 | true, 10 | "check-space" 11 | ], 12 | "curly": true, 13 | "eofline": true, 14 | "forin": true, 15 | "import-blacklist": [ 16 | true, 17 | "rxjs" 18 | ], 19 | "import-spacing": true, 20 | "indent": [ 21 | true, 22 | "spaces" 23 | ], 24 | "interface-over-type-literal": true, 25 | "label-position": true, 26 | "max-line-length": [ 27 | true, 28 | 140 29 | ], 30 | "member-access": false, 31 | "member-ordering": [ 32 | true, 33 | "static-before-instance", 34 | "variables-before-functions" 35 | ], 36 | "no-arg": true, 37 | "no-bitwise": true, 38 | "no-console": [ 39 | true, 40 | "debug", 41 | "info", 42 | "time", 43 | "timeEnd", 44 | "trace" 45 | ], 46 | "no-construct": true, 47 | "no-debugger": true, 48 | "no-empty": false, 49 | "no-empty-interface": true, 50 | "no-eval": true, 51 | "no-inferrable-types": [ 52 | true, 53 | "ignore-params" 54 | ], 55 | "no-shadowed-variable": true, 56 | "no-string-literal": false, 57 | "no-string-throw": true, 58 | "no-switch-case-fall-through": true, 59 | "no-trailing-whitespace": true, 60 | "no-unused-expression": true, 61 | "no-use-before-declare": true, 62 | "no-var-keyword": true, 63 | "object-literal-sort-keys": false, 64 | "one-line": [ 65 | true, 66 | "check-open-brace", 67 | "check-catch", 68 | "check-else", 69 | "check-whitespace" 70 | ], 71 | "prefer-const": true, 72 | "quotemark": [ 73 | true, 74 | "single" 75 | ], 76 | "radix": true, 77 | "semicolon": [ 78 | "always" 79 | ], 80 | "triple-equals": [ 81 | true, 82 | "allow-null-check" 83 | ], 84 | "typedef-whitespace": [ 85 | true, 86 | { 87 | "call-signature": "nospace", 88 | "index-signature": "nospace", 89 | "parameter": "nospace", 90 | "property-declaration": "nospace", 91 | "variable-declaration": "nospace" 92 | } 93 | ], 94 | "typeof-compare": true, 95 | "unified-signatures": true, 96 | "variable-name": false, 97 | "whitespace": [ 98 | true, 99 | "check-branch", 100 | "check-decl", 101 | "check-operator", 102 | "check-separator", 103 | "check-type" 104 | ], 105 | "directive-selector": [ 106 | true, 107 | "attribute", 108 | "app", 109 | "camelCase" 110 | ], 111 | "component-selector": [ 112 | true, 113 | "element", 114 | "app", 115 | "kebab-case" 116 | ], 117 | "use-input-property-decorator": true, 118 | "use-output-property-decorator": true, 119 | "use-host-property-decorator": true, 120 | "no-input-rename": true, 121 | "no-output-rename": true, 122 | "use-life-cycle-interface": true, 123 | "use-pipe-transform-interface": true, 124 | "component-class-suffix": true, 125 | "directive-class-suffix": true, 126 | "no-access-missing-member": true, 127 | "templates-use-public": true, 128 | "invoke-injectable": true 129 | } 130 | } 131 | --------------------------------------------------------------------------------