# ReleasePlatform **Repository Path**: lomospace/ReleasePlatform ## Basic Information - **Project Name**: ReleasePlatform - **Description**: Angular 5.x版 | app 发布平台 - **Primary Language**: TypeScript - **License**: Not specified - **Default Branch**: develop - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2018-02-05 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ReleasePlatform [![Build Status](https://travis-ci.org/lomo1/ReleasePlatform.svg?branch=develop)](https://travis-ci.org/lomo1/ReleasePlatform) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1892/badge)](https://bestpractices.coreinfrastructure.org/projects/1892) This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.6.6. ## Development server 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. ## Code scaffolding Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. ## Build 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. ## Running unit tests Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). ## Running end-to-end tests Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). ## Further help 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). ## UI库 > ng-zorro ```bash npm install ng-zorro-antd --save ``` API: https://ng.ant.design/#/docs/angular/getting-started ### ng-zorro常见问题 1. 模态框回调问题: > https://ng.ant.design/#/components/modal 点击button在点击确认后,发起HTTP请求回调函数时,编译打包通过,浏览器执行到请求时,提示http undefined, 实际上该`http`已定义在类中`private http: FetchReuqestService,` 官方api里给的`onOk`写法: ```js onOk() { console.log('确定'); }, ``` 最好改为: ```js onOk: () => { console.log('确认删除项目: ' + item['name']); this.http.postRequest(this.deleteProjectURL, 'projectShortName=' + item.shortName).then(//...); }, onCancel () { console.log('取消删除项目: ' + item['name']); } ``` 参考:https://github.com/NG-ZORRO/ng-zorro-antd/issues/409 ## 组件 结构图: TODO: ### Header > ng g component navbar ### SideBar > ng g component sidebar ### Footer > ng g component footer ### utils > ng g service utils --flat=false ### 核心功能组件 > 核心功能模块:项目总览、项目管理、产物管理 其它如:权限配置与管理等。 #### 项目总览 `projectOverview` > ng g module projectOverview --routing 在子模块下创建组件(会在project-overview文件夹下创建组件overview/) > ng g component projectOverview/overview 创建不生成spec测试文件的方法:添加参数 `--spec=false`, 默认为True 如: `ng g component projectManage/ChannelEmailConfig --spec=false` #### 项目管理 > 该模块功能最繁杂! > 子模块下的组件使用第三方UI组件(如:zorro), 在根模块上`@NgModule` imports后,子模块需要单独再引入一次,否则运行时浏览器控制台会报错(编译/打包时没问题) 项目管理模块设置为APP的一个子模块,该子模块的核心功能 包括以下几个组件. 子模块名: `projectManage` 创建子模块 > ng g module projectManage --routing 创建子组件 > ng g component projectManage/manage ##### 组件1:项目管理首页 > 包括已有项目列表,新建项目入口; ##### 组件2:项目配置 > 包括Android配置、RN配置、iOS配置、发布官网配置(针对安卓)、渠道发布收件人等配置。 ##### 组件3:项目权限管理配置 #### 产物管理 产物管理模块设置为APP的一个子模块,该子模块的核心功能: > 包括每个APP的iOS、Android历史版本查看入口、操作日志等等. > 子模块名: `productManage`. 下属各个组件分别对应: 1. **历史版本列表(Android、iOS)组件** 2. **操作日志查看组件** 创建子模块 productManage > ng g module productManage 创建子模块productManage的组件: > ng g component productManage/productManage #### 构建管理 > 2018-04 新增需求 > ng g module buildManage --routing 自动创建带路由配置的子模块。 添加路由`path`和`component`后,可能会报错: ```bash webpack: Compiled successfully. ERROR in src/app/build-manage/build-manage-routing.module.ts(4,7): error TS2322: Type '{ path: string; component: string; }[]' is not assignable to type 'Route[]'. Type '{ path: string; component: string; }' is not assignable to type 'Route'. Types of property 'component' are incompatible. Type 'string' is not assignable to type 'Type'. ``` 问题:子路由语法错误. ```json { path: '', component: BuildIndexComponent } ``` > #### 用户管理 子模块:userManage 用户管理 > ng g module userManage --routing 子组件: > ng g component userManage/userManage ### 自定义Service #### fetch request > ng g service xxServiceName, ng g service xxServiceName --flat=false (带文件夹的, flat默认为TRUE) 如: ```bash # -flat默认值为TRUE》 FALSE时表示该Service不在app根目录下创建xx.ts文件,而是在app目录下新建文件夹(名为fetch-requet),第二个单次如果大写则会被ng命令直接以"-"连接 并将第二个单词改为小写; 如果都是小写单词则不会被-链接。 当`credentials` => `include`时,表示cookie既可以同域发送,也可以跨域发送; 此时,后端接口返回的Response Headers里的`Access-Control-Allow-Origin`值不能为`*`,此为浏览器限制,实际上接口成功返回。 那么,如何解决既要跨域请求又能携带Cookie呢? 解决方案: 1. `credentials` 设置为 `include` 2. 后端接口的Response Headers内的`Access-Control-Allow-Origin`不能为*, 必须指定完整的域信息. > 以上2个步骤缺一不可! 此时`mode`设置:`mode: 'no-cors'` !!!,如果还设置为cors则提示跨域问题错❌, 设置为no-cors时,控制台报错,拿不到数据!!! 设置为`no-cors`时Method只能为head/get/post 参考: > https://segmentfault.com/a/1190000008484070 , http://blog.csdn.net/codetomylaw/article/details/52588493 ng g service fetchReuqest --flat=false ``` 说明: `fetch-requet` Service 封装了浏览器最新HTTP请求服务 fetch。 参考文档及浏览器支持情况: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch > IE11 不支持Fetch API !!! > OSX 的Safari 10.0也不支持Fetch; 版本 10.0 (12602.1.50.0.10) 使用Fetch进行POST请求,如果要传递参数以`From`形式(即: 抓包查看在Contents一栏有From,每一行对应一个key和value,这样后端如php就可以直接使用$_POST接受。),如果是上传文件,则使用formData传递参数; #### http request 内置的HTTP服务进行简单封装; 当在IE11环境下时就应该使用该服务,ng2+的`HttpClient`模块是基于xhr的。 NG2内置的HTTP服务在进行POST跨域请求时,需要注意: 如果跨域请求时要求客户端携带Cookie信息,则需要在post()中添加参数`withCredentials: true`,且后端接口也要设置对应的允许域,且设置值不能为`*`, 这点和上面的Fetch一样. > Angular5.x以上版本,HTTP请求使用 HttpClient模块,而不是Http;`import { HttpClient } from '@angular/common/http';` ## 打包 `ng build -prod`, 如果未使用hash路由方式,则复制带path的URL在浏览器打开404(因为被当做一个资源URL请求服务器,服务找不到). 改用hash,修改`app.module`.ts`里的imports: `RouterModule.forRoot(appRoutes, {useHash: true})` TODO: 1. 如何组织一个应用里的多个API URL(而不是将API地址分别写死在某个组件或业务代码里)? Done. at 2018-03 > 常量类; 2. ng2图表插件引入(for angular 5.x, echarts or highcharts ?) > 已解决 3. 子模块、子路由参考: http://blog.csdn.net/u012706811/article/details/70162336 http://blog.csdn.net/franktaoge/article/details/60769501 > 已解决 4. 代码优化 5. Android等配置页 CheckBox复选框后期抽离成子组件(与`authority-manage-child`组件类似), 尽量避免DOM直接操作 > 目前对CheckBox 复选框的动态循环创建使用的是基于元素API。值的获取使用了CSS选择器, 依赖于DOM, 后期improve. 6. 渠道收件人组件里 初始化请求获取数据,当还未配置过时,初次进入,接口返回的`returnCode=0`,但是数据为空,获取不到`ccList`和`toList`。但是不影响功能,只在控制台报错,需要进一步提升、完善代码. 7. 一键式平台中首次进入接口请求错误,多次请求问题:导致最后一次请求未携带参数,接口返回错误信息: `接口返回信息: platform、projectShortName字段不能为空错误码: 1` 8. 打包压缩问题(TODO:) > ng build -prod后,通过dom获取数据问题, css选择器找不到 ,导致getAttribute无法使用。 ``` ERROR TypeError: Cannot read property 'getAttribute' of null at n.submit (3.7f5b2d91a64ca1db1a65.chunk.js:1) at Object.handleEvent (3.7f5b2d91a64ca1db1a65.chunk.js:1) at Object.handleEvent (main.f228ede59a9e3e8d2a5d.bundle.js:1) at Object.handleEvent (main.f228ede59a9e3e8d2a5d.bundle.js:1) at ve (main.f228ede59a9e3e8d2a5d.bundle.js:1) at main.f228ede59a9e3e8d2a5d.bundle.js:1 at HTMLButtonElement. (main.f228ede59a9e3e8d2a5d.bundle.js:1) at e.invokeTask (polyfills.97345be80d14dfd7d44b.bundle.js:1) at Object.onInvokeTask (main.f228ede59a9e3e8d2a5d.bundle.js:1) at e.invokeTask (polyfills.97345be80d14dfd7d44b.bundle.js:1) ``` 但是 `ng build` 或 `ng build --aot` 编译出来的dist是ok的。 问题缘由: 在获取复选框值时使用了原生的document操作获取值,`document.querySelector('label[ng-reflect-name=' + checkboxKey + ']>span> input').getAttribute('ng-reflect-model');`, 而其中的`ng-reflect-name`属性属于在本地开发阶段时才会有的, `ng-reflect-${name} attributes are added for debugging purposes... They exist only when debugging mode is used - default mode for Angular ` from stackoverflow ~. 参考: https://stackoverflow.com/questions/43397839/what-does-the-ng-reflect-attribute-do-in-angular2-4 ### 路由 #### 路由传参数 引入依赖: ```ts import { Router } from '@angular/router'; // init router: Router .. // 传递多参数, 使用navigate 而非navigateByUrl! this.router.navigate(['/projectManage/projectConfig'], {queryParams: { id: 1, shortName: 'lomo' }}); ``` 接受参数: ```ts // 依赖 import { ActivatedRoute, Params } from '@angular/router'; // init activatedRoute // 接受参数 activatedRoute.queryParams.subscribe(queryParams => { console.log(JSON.stringify(queryParams)); }); ``` 第二种参数传递: > 直接在模板里 ```html ``` 获取参数: ```ts console.log(this.activatedRoute.snapshot.params['shortName']); ``` ### 项目分支说明 #### master分支 > 保留分支; prod发布版本; #### develop分支 > 当前开发分支; #### chart分支 > 示例分支: 图表📈 `Echarts`等 #### dynamicInput分支 > 示例分支: 动态创建表单(input绑定问题)的测试分支 #### upload分支 > 示例分支: 文件上传示例; 使用原生H5标签. 后期改为nz-upload ### 项目语法(tslint)错误提示 1. 使用for in 语句时 ```ts for (const i in this.validateForm.controls) { this.validateForm.controls[i].markAsDirty(); } ``` tslint会提示如下: ```bash [tslint] for (... in ...) statements must be filtered with an if statement (forin) (property) AuthorityManageComponent.validateForm: FormGroup ``` 解决: 使用`hasOwnProperty` 加个`if`判断即可. ```ts for (const i in this.validateForm.controls) { if (this.validateForm.controls.hasOwnProperty(i)) { this.validateForm.controls[i].markAsDirty(); } } ``` 参考: https://stackoverflow.com/questions/1963102/what-does-the-jslint-error-body-of-a-for-in-should-be-wrapped-in-an-if-statemen 2. tslint 提示max-line-lenth问题 如有代码: `const key = this.inputParamsList[i]['defaultParameterValue']['value'] ? this.inputParamsList[i]['defaultParameterValue']['value'] : this.inputParamsList[i]['name'];` 这一行代码长度超过140,根据`tslint.json`文件里的配置参数`max-line-length`最大值默认为140,可适当调整其最大值即可。单行代码过长不便阅读。 3. escape与unescape > escape与unescape是ES5中的语法。 ```js var a = escape("&#"); console.log(a); // %26%23 var b = unescape(a); console.log(b); // &# ``` ES6, 推荐使用encodeURI. 参考: https://github.com/Microsoft/TypeScript/issues/8639 ### 正则相关 URL校验正则表达式: `[a-zA-z]+://[^\s]*`, ❌, `httpa://` 这种不是不对的,但是也能match该正则. 正确写法: `(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]`