Iit

来自ling
跳转至: 导航搜索

http://tmslnxdev2.ling2.cn/base/swagger-ui.html

http://tmslnxdev2.ling2.cn/iit/swagger-ui.html

@翊凝 system/999999  系统管理员   1234567890/Deloitte_2018  租户管理员   1234567890006/Deloitte_2018/  HR组织管理员     1234567890011/Deloitte_2018  普通员工 test88/123456_aA 
sq24@sq.com


http://tmslnxdev2.ling2.cn:8500/iit/ http://localhost:8500/iit/ http://tmslnxdev1.ling2.cn/jenkins/ 用户:admin/Tax.123456 developer/Dev_123456

http://tmslnxdev1.ling2.cn/gitlab/ 用户: root/Tax!23456

47.101.169.7 tmslnxdev001 tmslnxdev1 tmslnxdev2 tmslnxdev001.ling2.cn tmslnxdev1.ling2.cn tmslnxdev2.ling2.cn

47.101.157.56 tmslnxtest001

http://47.101.169.7/#/deductionexport


47.101.169.7 tmslnxdev001 tmslnxdev1 tmslnxdev2

47.101.157.56 tmslnxtest001

tmslnxdev001.yujiedu.com

目录

需求

Iit flow.jpg

启动项目

启动portal

npm config set cache "D:\server\nodejs8.12.0\node_cache"
npm config set prefix "D:\server\nodejs8.12.0\node_global"
npm config ls
npm install -g yarn
npm install -g nrm
nrm ls #可以查看npm的数据源,通过nrm use xxx进行切换
nrm use taobao

npm install -g @angular/cli
  • yarn install
  • 修改 tms-portal\src\environments\environment.hmr.ts 中 IIT_SERVER_URL: `http://localhost:8500/iit/`,
  • ng serve -c=hmr
  • admin 88888

后端java编码规范

java

orm

service

controller

前端angular编码规范

  • 所有的modules,components和view必须使用命令行创建
  • 公共组件在创建在ng generate component shared/components/.....里面
  • 组件名称中有多个单词的,用-隔开,比如DictSelect ng命令后生产的文件夹位dict-select

方法定义与暴露

  • 内部为handelXXX
  • 外部实现为onXXX
  handleCancel = (e) => {
    const onCancel = this.props.onCancel;
    if (onCancel) {
      onCancel(e);
    }
  }

angular 组件生成和命名规范

modules

  • 模块名称用小写一个单词描述,一个单词描述不清楚的用-隔开,比如person-info
  • 模块必须用命令生成
ng generate module base/personinfo
  • 生成后,在对用的.module.ts中添加公共模块的引用
  imports: [
    SharedModule, CommonModule,
  ],
  • 因为历史原因,新建模块需要手工在src\app\base\base.module.ts,src\app\app.module.ts,src\app\routes\routes.module.ts 中手工注册

vo

  • 与后端的vo保持一致
  • 位置\src\app\module\vo\response 比如base模块vo在 \src\app\base\vo\response
  • 尽量区分request和response,后端vo相对应的vo放在response中
  • 示例
import { AbstractVo } from '@shared/result/abstract-vo';

export class BaseDictVo extends AbstractVo {
    baseDictUuid: string;
    dictName: string;
    dictCode: string;
    enumsClassName: string;
    tenantId: string;
}

componts

  • 组件名称用小写一个单词描述,一个单词描述不清楚的用-隔开,比如person-info
  • 组件必须用命令生成
  • 每个组件必须带上module名称,比如personinfo,personinfo-rent.因为比如都叫rent,当其他模块有野rent组件,某个view需要使用2个模块的rent组件时会发生名称冲突.使用...module-组件名称的方式也便于定位所使用组件的位置
ng generate component base/personinfo/components/personinfo
ng generate component base/personinfo/components/personinfo-rent
ng generate component base/personinfo/components/personinfo-child-edu
ng generate component base/personinfo/components/personinfo-elder

views

  • view名称用小写一个单词描述,一个单词描述不清楚的用-隔开,比如person-info
  • 组件必须用命令生成
  • 生成页面
ng generate component shared/views/dict-select-test
ng generate component base/personinfo/views/personinfo-index
  • 配置路由
src\app\routes\routes-routing.module.ts 中配置路由
{
    path: 'share',
    children: [
      {
        path: 'dictselecttest',
        component: DictSelectTestComponent,
        canActivate: [AuthRouteGuard],
      },
    ],
  }
  • 打开路由访问

http://localhost:4200/#/share/dictselecttest

  • 配置菜单

src\assets\app-data.json

功能使用规范

表格

https://ng-alain.com/components/table/zh

表单

https://ng-alain.com/form/getting-started/zh

公共组件

  • 公共组件在创建在ng generate component shared/components/.....里面
  • 命名规范参考iit#componts
ng generate component shared/components/dict-select
dict

dict-select

ng generate component shared/components/dict-select
<dict-select [groupCode]="groupCode" width="260" [(itemValue)]="itemValue" nzPlaceHolder="111111111111111"></dict-select>

dict-translate

ng generate component shared/components/dict-translate
ng generate component mobile/share/components/dict-select-m

ng generate component mobile/share/components/dict-translate-m 通用

ng generate component mobile/share/views/dict-test
移动端日期控件
ng generate component mobile/share/components/date-picker-m


<date-picker-m [(value)]="dateValue1" title="dateValue1"></date-picker-m>
<date-picker-m [value]="dateValue2" title="dateValue2" [disabled]="datePickerDisabled"></date-picker-m>

原生控件支持的属性都支持,包括disable和valuechange和双向绑定,支持字符串和Date类型,选择后传出 的是Date类型

注意默认时间格式是YYYY-MM-DD,时间格式参考 http://momentjs.cn/docs/#/parsing/ 的说明

传入2018-11-01 12:12,格式是YYYY-MM-DD是支持的

YYYY-MM-DD HH:mm:ss这样的格式需要配合mode="datetime"时分秒才能有值

如果非标准格式请自己传入format属性

优化了返回值this.value_ = DateUtil.parse(DateUtil.formatDate(result, format_), format_);

如果要得到时分秒,可以使用mode=datetime或传入自定义format

getFormat() {
    if (this.format) {
      return this.format;
    } else if (this.mode) {
      if ('datetime' === this.mode) {
        return 'YYYY-MM-DD HH:mm:ss';
      }
      if ('date' === this.mode) {
        return 'YYYY-MM-DD';
      }
      if ('time' === this.mode) {
        return 'HH:mm:ss';
      }
    } else {
      return 'YYYY-MM-DD';
    }
  }
export

Angular表格的导入导出

ng generate component shared/components/excel-front-export
ng generate component shared/components/excel-end-export
ng generate component shared/views/excel-export-index
导入
ng generate component shared/components/excel-end-import
页面级权限控制

[1]

directive


SessionManager#login(loginForm: LoginForm): Promise<boolean>
...
ACL原始数据:{{ aclSrv.data | json }}
 <button nz-button [acl]="'admin'" class="ml-sm">role-b</button>

Angular2使用Guard和Resolve进行验证和权限控制

ng generate component shared/views/base-test
ng generate component shared/views/base-test/components/base-test1
ng generate component shared/views/base-test/components/base-test2
ng generate interface shared/interface/PageSecurity

iit组件

ng generate component iit/deduction/components/claim-l-table
ng generate component iit/deduction/components/claim-summary
ng generate component iit/deduction/components/claim-query-form
ng generate component iit/deduction/components/claim-h-table

doc

ng generate doc
ng generate component doc/views/org-txt

模块和api

扣除申请

字典

专项附加扣除类型数据字典
子女教育	childEdu	通过数据在表BASE_PERSONAL_INFO_FAMILY里的字段RELATIONSHIP来判断,如果附件数据所关联的记录行该字段=子女则该附件属于childEdu,否则属于elder	
赡养老人	elder		
学历继续教育	schoolEdu	通过数据在表BASE_PERSONAL_INFO_CE里的字段CERTIFICATE是否为空来判断,如果附件数据所关联的记录行该字段为空则该附件属于SchoolEdu,否则属于CareerEdu	
职业继续教育	careerEdu		 
大病医疗	criticalIllness	 	注意illness
贷款利息	loanInterest	 	
房屋租金	rental

扣除申请首页(税务日历)

IitDeuctionClaimController#findDeuctionClaim
/**
     * 申报期间主键
     */
    private String iitdeduClaimHUuid;
    /**
     * 期间名称
     */
    String periodName;
    /**
     * 年份
     */
    int pierodYear;
    /**
     * 月份
     */
    int pierodMonth;
    /**
     * 申报状态
     */
    String deduClaimStatus;
    /**
     * 已申报
     */
    Double appedAmount;
    /**
     * 已验证
     */
    Double validatedAmount;
    /**
     * 待验证
     */
    Double validatingAmount;
数据需要支持动态显示:
根据当前用户,查询DEDUCTION_CLAIM_H中相应年、月的申请单,根据DEDUCTION_CLAIM_L申请单状态显示金额:
已验证:所有申请单状态为“已审核”的单据金额总和
已申报:目前显示为0
待校验:申请单状态为“未提交”、“待修改”、“待审核”的申请单总金额

@柴一周 数据需要支持动态显示:
* 这个状态有三个,即:未提交(时间未到)、申请中(目前系统时间在征期的时间范围内,且下属的单据没有全部标为“已审核”)、已完成(时间已过)
 bo.wang
这个和数据库的字段没关系?
 bo.wang
当前日期和和头数据的周期的结束时间比较?

个税截止日期天数

get http://tmslnxdev2.ling2.cn:8500/iit/deuctionClaim/getDaysOfDeadLineByYearMonth?year=2018&month=9

IitDeuctionClaimController#getDaysOfDeadLineByYearMonth

当前待审批数据条数

get http://tmslnxdev2.ling2.cn:8500/iit/deuctionClaim/getReviewingNumOfCurrentDay

IitDeuctionClaimController#getReviewingNumOfCurrentDay

获取当前用户某个年月的申报明细数据

get http://tmslnxdev2.ling2.cn:8500/iit/deuctionClaim/getDeductionClaimDetailOfCurrentUser?year=2018&month=11

获取行对应的家庭关系

get http://tmslnxdev2.ling2.cn:8500/iit/deuctionClaim/getIitFamilyRelationByRelationshipOfCurrentUser?relationship=子女 get http://tmslnxdev2.ling2.cn:8500/iit/deuctionClaim/getIitFamilyRelationByRelationshipOfCurrentUser?relationship=父母

获取行对应的附件

get http://tmslnxdev2.ling2.cn:8500/iit/deuctionClaim/getAttachmentByClainmLId?iitDeductionClaimLUuid=5bab3df59b100000

获取行对应的附件类型和文件数量

get http://tmslnxdev2.ling2.cn:8500/iit/deuctionClaim/getAttachmentGroupByClainmLId?iitDeductionClaimLUuid=5bab3df59b100000

附件上传

post http://tmslnxdev2.ling2.cn:8500/iit/deuctionClaim/uploadClaimLAttachment

{
file:file,
iitDeductionClaimLUuid:'5bab3df59b100000',
iitFileTypeUuid:'5bab4fb87b100000'
}

企业HR人工校验

*头数据提交 post http://tmslnxdev2.ling2.cn:8500/iit/deuctionClaim/submitIitDeductionClaimH
 {ids:"a,b"}
 {ids:"a,b"}
 {ids:"a,b"}
 DeductionClaimDetailLVo
 DeductionClaimDetailLVo
 DeductionClaimDetailLVo

人员基础信息维护BasePersonalInfo

前端接口

ng generate module base/personinfo
  imports: [
    SharedModule, CommonModule,
  ],
ng generate component base/personinfo/views/personinfo-index
ng generate component base/personinfo/components/personinfo
ng generate component base/personinfo/components/personinfo-rent
ng generate component shared/components/dict-select

后端接口

  • 获取basePersonalInfoUuid的待修改的学历继续教育数据
get base/basePersonalInfo/getBasePersonalInfoCeVosByPersonId_jixu
req:{basePersonalInfoUuid:String}
response List<BasePersonalInfoCeVo>
  • 获取basePersonalInfoUuid的待修改的职业资格继续教育数据
get base/basePersonalInfo/getBasePersonalInfoCeVosByPersonId_zhiye
req:{basePersonalInfoUuid:String}
response List<BasePersonalInfoCeVo>
  • 批量保存basePersonalInfoUuid的学历/职业资格继续教育数据
post base/basePersonalInfo/updateBasePersonalInfoCeVosByPersonId
req{basePersonalInfoUuid:String,basePersonalInfoCeVos:List<BasePersonalInfoCeVo>}
response
  • 获取basePersonalInfoUuid的待修改的租金信息
get base/basePersonalInfo/getBasePersonalInfoRentalVosByPersonId
  • 批量保存basePersonalInfoUuid的租金信息
post base/basePersonalInfo/updateBasePersonalInfoRentalVosByPersonId
req{basePersonalInfoUuid:String,basePersonalInfoRentalVos:List<BasePersonalInfoRentalVo> }
response
  • 获取所有可上传的文档类型列表
get base/basePersonalInfo/getBaseAttachmentDocTypeVos
response List<BaseAttachmentDocTypeVo>
  • 上传人员基础信息对应的文档
post base/basePersonalInfo/uploadBasePersonalInfoAttachmentVo
req {file:MultipartFile,baseAttachmentDocTypeUuid:String,basePersonalInfoUuid:String,personalInfoTypeId :String}
response BasePersonalInfoAttachmentVo

用户导入

  • 你明天抽时间做以下功能:把用户导入后,初始化密码为身份证后六位,用户登录后检查是否密码还是初始化密码,如果是,就强制要求更改密码。密码有大小写和数字策略。谢谢

ng generate component base/passport/login/init-password

消息中心

参考海量消息概要设计

ng generate module base/message
ng generate component base/message/components/message-topic-table
ng generate component base/message/views/message-topic-manager
ng generate component base/message/components/message-send-table
ng generate component base/message/views/message-send-manager
ng generate component base/message/components/message-rec-table
ng generate component base/message/views/message-rec-manager

生成后,在对用的.module.ts中添加公共模块的引用

 imports: [
   SharedModule, CommonModule,
 ],

BasePeriod

期间

ng generate component base/period/components/period-modal
ng generate component base/period/views/period-manager

消息定时任务

@bo.wang 后台定时任务的实现中,采用ServiceHelper.injectSystmSession()来注入超级管理员session

@bo.wang criteria.setAutoFilterDataIsaolation(false),框架就不做任何自动过滤了,如果是超级用户,应该是可以查到所有数据的,只要你把tenantId和orgId作为参数去过滤

@bo.wang ServiceHelper增加注入TenantId和OrgId的方法injectSystemSession(String tenantId, String orgid)

criteria.setAutoFilterDataIsaolation(false);
criteria.add(Restrictions.eq("tenantId", tenantId));
criteria.add(Restrictions.eq("orgId", orgId));


王波:

定时任务这块底层用的spring-quartz框架,欧春辉这边已经实现了根据界面上企业设置自动生成定时任务的功能。
      你这边要做的事情就是开发具体的定时任务实现接口:
1、	定时器每次会给你的接口一个上下文,比如租户ID、企业ID等必要信息
2、	你的接口需要把具体执行的任务内容开发出来,比如去自动为组织管理员审批所有专项附加扣除申请

@杜宇杰 杜老师,如何设置当前线程和子线程的tenantId和orgId,这个需要我管么?我发现我调用方然的方法,很多查询和判断都是基于当前回话的tenantId和orgId.而定时任务默认这些值是没有的吧

  • 专项附加扣除审核待办提前通知 DeduApproveRemindAheadDaysJob
  • 专项附加扣除申请待办提前提醒 DeduClaimRemindAheadDaysJob
  • 专项附加扣除申请完成日 DeduClaimLastdayJob
  • 专项附加扣除审核完成日 DeduApproveLastdayJob
  • 专项附加扣除结果推送日 DeduIssueLastdayJob
  • 1、 自动为员工创建待办DeduClaimRemindAheadDaysJobDeduClaimAutoCreateEmployeeApplicationJob


  • 2、 自动为员工提交专项附加扣除申请 DeduClaimAutoSubmitEmployeeApplicationJob
  • 3、 自动为组织管理员创建审批专项附加扣除待办 DeduClaimAutoAuditEmployeeApplicationJob
  • 4、 自动为组织管理员审批所有专项附加扣除申请
  • 5、 自动推送专项附加扣除结果至企业邮箱
  • 6、 自动推送专项附加扣除结果至个人邮箱

分摊协议的校验规则确认

就在赡养老人点保存的时候,检查个人信息中的“是否独生子女”和“分摊方式”,检查赡养老人的附件 不满足条件不让保存

分摊协议的校验规则确认.jpg

图上有错误

应该是:个人信息里,是否独生子女为“否”时,分摊方式不是“平均分担“时,附件中必须包含“分摊协议”

国际化

https://github.com/ngx-translate/core

多语言切换

<header-i18n></header-i18n> 

菜单多语言

  • app.module.ts
  • 在assets/i18n/中配置菜单多语言文件
  • 菜单格式中使用
 {
              "text": "Dynamic Form",
              "link": "/delon/form",
              "i18n": "dynamic-form"
            }

src\app\core\i18n\i18n.service.ts

  • 负责框架的多语言切换实现和多语言资源整合
  • 加载多语言资源
// 加载i18n语言文件
export function I18nHttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http, `assets/i18n/`, '.json');
}

添加自定义语言比如日语

src\app\core\i18n\i18n.service.ts中
const LANGS: { [key: string]: LangData } = {...
后追加
  jp: {
    text: '中文',
    ng: ngZh,
    zorro: zh_CN,
    dateFns: df_zh_cn,
    delon: delonZhCn,
  }
  • ng标识的是angular的语言资源
  • zorro是antd的语言资源
  • dateFns是日期格式的语言资源
  • delon是delon的语言资源,delon没有实现中文和英文外的语言资源.所有需要自定义一个文件资源,然后将值引用到这个节点中

Delon-lang.PNG

多语言的使用方法

框架默认使用以下插件完成前端多语言,更多参考 https://github.com/ngx-translate/core

    "@ngx-translate/core": "^10.0.1",
    "@ngx-translate/http-loader": "^3.0.1",

前端翻译

代码参考 http://localhost:4200/#/share/i18ntest

配置多语言资源文件和资源
  • 在assets/i18n/中配置菜单多语言文件和资源内容,比如
    "HELLO": "hello {{value}}","测试中文i18n":"jp i18n test",
在代码中的使用参考如下
  • js中
private translate: TranslateService
let child= this.translate.instant('子女');
  • 不带参数
<page-header [title]="'企业专项附加扣除规则管理'|translate"></page-header>
<div translate>测试中文i18n</div>
<div [translate]="'测试中文i18n'"></div>
{{'测试中文i18n'|translate}}
  • 带参数
 <div>{{ 'HELLO' | translate:{value: 'world'} }}</div>
 <div [translate]="'HELLO'" [translateParams]="{value: 'world'}"></div>
 <div translate [translateParams]="{value: 'world'}">HELLO</div>
  • Use HTML tags:

You can easily use raw HTML tags within your translations.

{
    "HELLO": "Welcome to my Angular application!<br><strong>This is an amazing app which uses the latest technologies!</strong>"
}
To render them, simply use the innerHTML attribute with the pipe on any element.

<div [innerHTML]="'HELLO' | translate"></div>

发布

https://ng-alain.com/docs/deploy/zh#%E5%AE%B9%E5%99%A8%E9%83%A8%E7%BD%B2

npm i -g webpack-bundle-analyzer@latest
ng build --prod --build-optimizer --stats-json
ng build --prod --build-optimizer

  • 命令如下,需要5g左右内存,耗时较多
npm run build

如果说内存不够,需要下面的命令

npm run build-max

nginx和https部署参考

    server {
        listen       80;
        listen       443 ssl;
        server_name  iit.ling2.cn;
 
        charset utf-8;
 
        location / {
          root /alidata/iit/;
          index  index.html index.html;
          proxy_set_header   Host             $host;
          proxy_set_header   X-Real-IP        $remote_addr;
          proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
        location /base {
          proxy_pass http://47.100.28.123/base;
          proxy_set_header   Host             $host;
          proxy_set_header   X-Real-IP        $remote_addr;
          proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          client_max_body_size    1000m;
        }
        location /iit {
          proxy_pass http://47.100.28.123/iit;
          proxy_set_header   Host             $host;
          proxy_set_header   X-Real-IP        $remote_addr;
          proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          client_max_body_size    1000m;
        }
        location /file {
          proxy_pass http://47.100.28.123/file;
          proxy_set_header   Host             $host;
          proxy_set_header   X-Real-IP        $remote_addr;
          proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          client_max_body_size    1000m;
        }
        location /websocket{
          proxy_pass http://47.100.28.123/websocket;
          proxy_set_header   Host             $host;
          proxy_set_header   X-Real-IP        $remote_addr;
          proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          client_max_body_size    1000m;
        }
        ssl_certificate      /etc/letsencrypt/live/wiki.ling2.cn/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/wiki.ling2.cn/privkey.pem;
    }

待解决问题

Cannot find module '@angular/core'

编译好的js报错,mobile可能需要换新框架

Can't bind to 'uploader' since it isn't a known property of 'input'

src\app\mobile\share\components\file-upload-m\file-upload-m.component.html

ERROR in : Can't bind to 'uploader' since it isn't a known property of 'input'. ("nClick)="onAttachmentClick()">附件上传 -->
                <input #fileUpload type="file" ng2FileSelect [ERROR ->][uploader]="uploader" accept="image/*" name="fileUpload"/>
            <!-- </div>  hidden=true-->
  ")


https://stackoverflow.com/questions/45303404/angular-2-cant-bind-to-uploader-since-it-isnt-a-known-property-of-input

You need to import FileUploadModule in the module that declares the component using 'upload' which in your case would be category-items.module.ts

category-items.module.ts

import { CategoryItemsComponent } from './category-items.component';

import { FileUploadModule } from "ng2-file-upload";   //Should import HERE

imports: [  ...FileUploadModule ... ]   //RIGHT PLACE

警告

C:\workspace\source\ng-alain>npm run build-max

> ng-alain@2.0.0-rc.1 build-max C:\workspace\source\ng-alain
> node --max-old-space-size=7000 node_modules\\@angular\\cli\\bin\\ng build --prod --build-optimizer


Date: 2018-11-27T17:58:48.484Z
Hash: 03452025293a5ba8c7ee
Time: 98883ms
chunk {scripts} scripts.67f74ed80b777e7645e1.js (scripts) 1.22 MB  [rendered]
chunk {0} runtime.06daa30a2963fa413676.js (runtime) 1.44 kB [entry] [rendered]
chunk {1} main.9868d9b237c3a48c54da.js (main) 128 bytes [initial] [rendered]
chunk {2} polyfills.85f47f0bf59079cbc23a.js (polyfills) 130 bytes [initial] [rendered]
chunk {3} styles.ae415e11672cf1870cb1.css (styles) 507 kB [initial] [rendered]

ERROR in : Cannot determine the module for class LayoutPassportComponent in C:/workspace/source/ng-alain/src/app/layout/passport/passport.component.ts! Add LayoutPassportComponent to the NgModule to fix it.
Cannot determine the module for class UserLockComponent in C:/workspace/source/ng-alain/src/app/routes/passport/lock/lock.component.ts! Add UserLockComponent to the NgModule to fix it.
Cannot determine the module for class UserLoginComponent in C:/workspace/source/ng-alain/src/app/routes/passport/login/login.component.ts! Add UserLoginComponent to the NgModule to fix it.
Cannot determine the module for class UserRegisterComponent in C:/workspace/source/ng-alain/src/app/routes/passport/register/register.component.ts! Add UserRegisterComponent to the NgModule to fix it.
Cannot determine the module for class UserRegisterResultComponent in C:/workspace/source/ng-alain/src/app/routes/passport/register-result/register-result.component.ts! Add UserRegisterResultComponent to the NgModule to fix it.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! ng-alain@2.0.0-rc.1 build-max: `node --max-old-space-size=7000 node_modules\\@angular\\cli\\bin\\ng build --prod --build-optimizer`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the ng-alain@2.0.0-rc.1 build-max script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     c:\server\nodejs8.12.0\node_cache\_logs\2018-11-27T17_58_48_625Z-debug.log

C:\workspace\source\ng-alain>npm run build-max

> ng-alain@2.0.0-rc.1 build-max C:\workspace\source\ng-alain
> node --max-old-space-size=7000 node_modules\\@angular\\cli\\bin\\ng build --prod --build-optimizer

                                                                                                                                                                                                          3
                                                                                                                                                                                                          6
                                                                                                                                                                                                          6
                                                                                                                                                                                                          6
                                                                                                                                                                                                        6
                                                                                                                                                                                                        6
                                                                                                                                                                                                        6
                                                                                                                                                                                                        6
Date: 2018-11-27T18:10:34.818Z
Hash: 9a7fd7944ab073b4a7a9
Time: 384956ms
chunk {scripts} scripts.67f74ed80b777e7645e1.js (scripts) 1.22 MB  [rendered]
chunk {0} runtime.4753625a917c70f0d5c4.js (runtime) 2.33 kB [entry] [rendered]
chunk {1} main.08fd81df7d7eabb36b50.js (main) 7 MB [initial] [rendered]
chunk {2} polyfills.f5782f08f91bc810ce95.js (polyfills) 99.5 kB [initial] [rendered]
chunk {3} styles.ae415e11672cf1870cb1.css (styles) 507 kB [initial] [rendered]
chunk {4} 4.1dde6b92f0ee9500e663.js () 166 kB  [rendered]
chunk {5} 5.9b50c9599e84d981a94b.js () 72 kB  [rendered]
chunk {6} 6.c85eb274c4da1fa74909.js () 166 kB  [rendered]
chunk {7} 7.5e0463386d9308f11fdb.js () 9.96 kB  [rendered]
chunk {8} 8.2080237cfa0c82cc593a.js () 12.7 kB  [rendered]

WARNING in ./node_modules/ionic-angular/umd/components/app/app-constants.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/gestures/gesture-controller.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/config/config.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/action-sheet/action-sheet-controller.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/app/menu-controller.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/app/app.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/platform/platform.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/alert/alert-controller.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/alert/alert.js 4:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/util/util.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/transitions/transition-wp.js 4:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/transitions/transition-md.js 4:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/platform/query-params.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/util/dom.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/transitions/transition-ios.js 4:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/platform/key.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/action-sheet/action-sheet.js 4:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/navigation/nav-util.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/navigation/view-controller.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/transitions/page-transition.js 4:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/action-sheet/action-sheet-transitions.js 4:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/action-sheet/action-sheet-component.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/alert/alert-transitions.js 4:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/components/alert/alert-component.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/animations/animation.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/navigation/nav-params.js 3:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/umd/transitions/transition.js 4:24-31
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

WARNING in ./node_modules/ionic-angular/util/ng-module-loader.js 30:11-36
Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/ionic-angular/util/ng-module-loader.js 20:11-36
Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/ionic-angular/util/ng-module-loader.js 30:11-36
System.import() is deprecated and will be removed soon. Use import() instead.
For more info visit https://webpack.js.org/guides/code-splitting/

WARNING in ./node_modules/ionic-angular/util/ng-module-loader.js 20:11-36
System.import() is deprecated and will be removed soon. Use import() instead.
For more info visit https://webpack.js.org/guides/code-splitting/

异步优化

优化前
消耗时间任务执行成功,耗时{85022}毫秒
消耗时间任务执行成功,耗时{48130}毫秒
消耗时间任务执行成功,耗时{47856}毫秒
第一次优化后
消耗时间任务执行成功,耗时{35679}毫秒
消耗时间任务执行成功,耗时{24346}毫秒
消耗时间任务执行成功,耗时{22303}毫秒
消耗时间任务执行成功,耗时{21830}毫秒
buildDetail_lvo 继续异步后
queryValidateIitDeductionClaimHVoAsync合计消耗时间:任务执行成功,耗时{25407}毫秒
queryValidateIitDeductionClaimHVoAsync合计消耗时间:任务执行成功,耗时{23670}毫秒
queryValidateIitDeductionClaimHVoAsync合计消耗时间:任务执行成功,耗时{22062}毫秒
queryValidateIitDeductionClaimHVoAsync合计消耗时间:任务执行成功,耗时{38996}毫秒
queryValidateIitDeductionClaimHVoAsync合计消耗时间:任务执行成功,耗时{21249}毫秒


convertIitDeductionClaimHToDeductionClaimDetailHVoAsync消耗时间:任务执行成功,耗时{12699}毫秒=buildDetail_lvo 前序任务消耗时间:任务执行成功,耗时{2212}毫秒+buildDetail_lvo 后续任务消耗时间:任务执行成功,耗时{10064}毫秒

buildDetail_lvo 后续任务消耗时间:任务执行成功,耗时{10064}毫秒=processPersionInfo消耗时间:任务执行成功,耗时{11916}毫秒+processMonthAmount消耗时间:任务执行成功,耗时{3060}毫秒+processYearSum消耗时间:任务执行成功,耗时{1624}毫秒

代码参考@Async#参考代码

租户外部接口

测试代码

  • maven依赖
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.3</version>
		</dependency>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpmime</artifactId>
			<version>4.5.3</version>
		</dependency>
  • 代码参考
package com.yujiedu.main.test;

import com.alibaba.fastjson.JSONObject;
import com.deloitte.tms.base.service.vo.response.base.BaseOrgVo;
import com.deloitte.tms.core.log.ILogger;
import com.deloitte.tms.core.log.LoggerFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;

public class TenantApiTests {
    protected static final ILogger logger = LoggerFactory.getLogger(TenantApiTests.class);
    private static final String DEFAULT_CHARSET = "UTF-8";

    public static void main(String[] args) throws Exception {
        File file = new File("C:\\Users\\jasonbwang\\Desktop\\orgimport.txt");
        Map<String, String> paramHeader = getHeaderParams();
        Map<String, String> paramBody = new HashMap<>();

//        String fileUrl = "http://127.0.0.1:8400/api/tenantApigCtrl/uploadTxtOrgData";
//        testRequestWithFile(fileUrl, file, paramHeader, paramBody);

        String jsonUrl = "http://127.0.0.1:8400/api/tenantApigCtrl/uploadRestfulOrgData";
        testRequestWithJson(jsonUrl, paramHeader);
    }

    private static void testRequestWithJson(String url, Map<String, String> paramHeader) throws Exception {
        List<BaseOrgVo> orgVos = new ArrayList<>();
        BaseOrgVo baseOrg = new BaseOrgVo();
        baseOrg.setOrgCode("TMC_DEMO_NR");
        baseOrg.setOrgAlias("TMC_DEMO_NR");
        baseOrg.setOrgName("上海德勤税务师事务所华北区TMC");
        baseOrg.setTaxpayerName("上海德勤税务师事务所华北区TMC");
        baseOrg.setTaxpayerIdentityNumber("20181202TMCNR");
        baseOrg.setVisual("N");
        baseOrg.setTop("N");
        baseOrg.setBaseProvinceUuid("北京市");
        baseOrg.setBaseCityUuid("北京市");
        baseOrg.setValidFromDateStr("2010-01-01");
        orgVos.add(baseOrg);

        String content2 = doPostWithJson(url, paramHeader, orgVos, DEFAULT_CHARSET);
        System.out.println(content2);
    }

    private static void testRequestWithFile(String url, File file, Map<String, String> paramHeader, Map<String, String> paramBody) throws Exception {
        String content1 = doPostWithFile(url, paramHeader, paramBody, file, DEFAULT_CHARSET);
        System.out.println(content1);
    }

    private static Map<String, String> getHeaderParams() {
        Map<String, String> paramHeader = new HashMap<>();
        paramHeader.put("request-timestamp", new Date().getTime() + "");
        paramHeader.put("request-uuid", UUID.randomUUID().toString());
        paramHeader.put("service-token", "");
        paramHeader.put("tenantId", "dev-dtt");
        paramHeader.put("orgId", "dev-tms");
        paramHeader.put("userId", "admin");
        paramHeader.put("token", "9cc8efaea7794a2a845792c478b9ec31");
        return paramHeader;
    }

    public static String doPostWithFile(String url, Map<String, String> paramHeader,
                                        Map<String, String> paramBody, File file, String charset) throws Exception {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(url);
        RequestConfig config = getQequestConfig();
        post.setConfig(config);

        // 设置Header
        if (paramHeader != null) {
            for (String key : paramHeader.keySet()) {
                post.addHeader(key, paramHeader.get(key));
            }
        }

        //添加文件
        FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        builder.addPart("file", fileBody);

        //设置body
        if (paramBody != null) {
            for (String key : paramBody.keySet()) {
                builder.addTextBody(key, paramHeader.get(key));
            }
        }

        HttpEntity entity = builder.build();
        post.setEntity(entity);
        String result = "";

        try {
            CloseableHttpResponse e = client.execute(post);
            HttpEntity resEntity = e.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(resEntity);
                System.out.println("response content:" + result);
            }
        } catch (IOException var10) {
            logger.error("请求异常", var10);
            var10.printStackTrace();
        }

        return result;

    }

    private static RequestConfig getQequestConfig() {
        return RequestConfig.custom().setSocketTimeout(30000).setConnectTimeout(20000).build();
    }

    public static String doPostWithJson(String url, Map<String, String> paramHeader,
                                        Object content, String charset) throws Exception {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String httpStr = null;
        HttpPost httpPost = new HttpPost(url);
        CloseableHttpResponse response = null;

        try {
            RequestConfig config = getQequestConfig();
            httpPost.setConfig(config);
            // 设置Header
            if (paramHeader != null) {
                for (String key : paramHeader.keySet()) {
                    httpPost.addHeader(key, paramHeader.get(key));
                }
            }
            //设置json值
            StringEntity stringEntity = new StringEntity(JSONObject.toJSONString(content), "UTF-8");//解决中文乱码问题
            stringEntity.setContentEncoding("UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
            response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            httpStr = EntityUtils.toString(entity, "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return httpStr;
    }
}

mfa

https://wt.deloitteresources.com/solutions/IAM/Pages/MFA_Technology_and_Support.aspx

token

嗯,我稍后提供下流程吧,基本就可以参考微信的,https://mp.weixin.qq.com/wiki?action=doc&id=mp1421140842&t=0.7414620752928431&highline=redirect%7C%26amp%3B_#0

dtt sap

公司网络下,可以

mount -t cifs //10.81.129.239/sap_test/ /data/sap_test/ -o username=sap_test,password=Deloitte_2018

DUYJ: 邮件里sap好像放的是生产目录:

mount -t cifs //10.81.129.233/sap/ /data/sap/ -o username=sap,password=Deloitte_2018,sec=ntlmssp,vers=3.0

DUYJ: 搞错了,10.81.129.233上的是SAP测试目录:

mount -t cifs //10.81.129.233/sap/ /data/sap_test/ -o username=sap,password=Deloitte_2018,sec=ntlmssp,vers=3.0

DUYJ: 测试环境吧,手工把文件放到测试环境中

柴一周: @bo.wang 那就是https://test.digiiit.deloitte.com.cn

柴一周: 组织导过来你直接创建一套新的吧,用户名密码你接受到数据进库了就有了

bo.wang: 租户建立好了吗

bo.wang: 还是我随便建立一个.这个环节的管理员用户名密码是什么?

柴一周: @bo.wang 随便建一个就行,账号密码我单独给你

https://test.digiiit.deloitte.com.cn/#/passport/login system / Deloitte_2018

DUYJ: 你要联调的话,本机hosts:

47.101.157.56   eurekasvr
47.101.169.7	postgresqlsvr mongodbsvr rocketmqsvr redissvr

DUYJ: 启动时加入参数

deploy.env=test


https://test.digiiit.deloitte.com.cn/#/passport/login

用户名 yuzhong@deloitte.com.cn 密码Deloitte_2018

ftp

47.101.216.74:2201 /usr/sap/tmp/DigiIIT/ 实际映射目录为/data/share/sap_test

bo.wang:
@杜宇杰 杜老师,dtt sap 说新文件在[‎24/‎01/‎2019 10:08]  Zhong, Yummy Yuanli (CN - Chongqing):  
/usr/sap/tmp/DigiIIT/ 

bo.wang:
我在47.101.216.74 dtt sap上看不到

bo.wang:
我们说的是一个地方么

username=sap,password=Deloitte_2018

sap

Steven: jessicakwang@deloitte.com.cn

Steven: IITiit-123456

Steven: 这个不行就试下帐号:leoyibliu@deloitte.com.cn

Steven: 密码:Azsxdcfv123/


Dear all,

根据今天跟客户SAP确认其提供的个性化需求表单列含义及需求,跟Hulk及IT开发同事确认Digi tool数据库表单,我们对SAP的个性化需求表单与数据库表单的MAPPING关系进行了添加。请各位对表单进行确认,以便确认后发送Jason尽快进行开发。之前咱们跟SAP agree 1月11号test数据。同时,请知晓:

1.	SAP的个性化需求表单是要导入他们的SAP系统,用于跑payroll使用,表单是标准化格式,不得增加或删减列;
2.	表3 “serious illness”暂不需配置开发;
3.	申请了专项扣除的员工信息才会列示在各表单,i.e.,如果某员工现在无子女,则其不会出现在表1 Children's education里;
4.	Remarks 1 and Remarks 2两列,内容留白,但该两列不得删除。该两列与现有的Digi 数据库表单无法mapping;、
5.	表2“CE”,数据库1中并未体现I列“education type”的信息,需区分技能人员职业资格“Occupational ability”和专业技术人员职业资格“Professional skill”。
6.	表6“ES”,F列"end date"需讨论如何获取该数据。

数据库1,在导出数据库的时候,选择下列"reviewed"-已审核数据,字段“tenent_id"租户账户选择SAP账户。
*SAP公司的tenant_id为5bb179aa840c000a

文件:Customized development template for SAP.20190104.xlsx 文件:File Specification 4DC 0109.xlsx

经过我们对SAP的第二轮测试,发现如下问题,烦请帮忙修改。


项目	表1-Children's Education	表2-Continuing Education	表4-Housing Loan	表5-Housing Rental	表6-Elderly Support
ID type/Child ID type/Parent ID type	客户要求身份证类型选01,其他类型证件选02;目前测试结果,无论证件类型,全部是02。
Education stage	客户要求选数字;目前测试结果,为带出Digi IIT里审核后的员工信息(如现在带出的是"primary school education";需要按提供的mapping规则一修改。	客户要求选数字;目前测试结果,为带出Digi IIT里审核后的员工信息(如,PHD);需要按提供的mapping规则二修改。	NA	NA	NA
Deduction Ratio	客户要求选数字, 0.5是1,100%是2;目前测试结果,为带出Digi IIT里50%/100%。	NA	NA	NA	NA
Child No	对于多个孩子扣除的情况,客户要求按孩子大小情况导出编号1,2,3等;目前测试结果,未能导出该编号。	NA	NA	NA	NA
Child 信息	对于多个孩子扣除的情况,客户要求逐一导出孩子信息;目前测试结果,仅能导出一个孩子的信息,遗漏其他孩子信息。	NA	NA	NA	NA
Education type	NA	对于属于职业继续教育的情况,客户要求选数字,1-技能人员职业资格,2-专业技术人员职业资格;目前测试结果,对于职业继续教育的情况,该数据未能导出。	NA	NA	NA
Begin date	NA	学历教育能带出数据,但是职业资格教育,未带出数据,需对应到Digi IIT的发证日期	目前测试结果,Begin date数据未导出。	NA	NA
End date	目前测试结果,End date数据未导出。	NA	目前测试结果,End date数据未导出。	NA	目前测试结果,Digi IIT里未填End date, 但导出的End date全部是”20190228“
Contract No.	NA	NA	目前测试结果,该数据数据未导出。	NA	NA
Work City	NA	NA	NA	目前测试结果,对于北京市,显示“BJS”,需要去掉S, 仅显示“BJ".	NA
Family type	NA	NA	NA	NA	客户要求选数字;目前测试结果,为带出Digi IIT里审核后的员工信息(如parenets);需要按提供的mapping规则四修改。
Only child	NA	NA	NA	NA	客户要求填选项X或者留空,X对应True, 留空对应False;目前测试结果,为带出True或False;需修改。

Hi 杜老师, 如刚才IM 沟通,烦请将城市名称首字母大写去掉S如“BJ代表“Beijing-北京市”,而非BJS。

Hi Jason, 如您提出的问题,已确认: 1.身份证类型选01,其他类型证件选02,非1,2 2. 子女教育表中deduction ratio: 1 - 100%, 2 - 50%

如有任何问题,请随时提出沟通,谢谢。

Hi Jason,
经与客户讨论,在按月份导出数据的设置那里,客户要求也支持从几月至几月的同时几个月的数据的导出;按entity导出的设置不需修改,还是按照一个ENTITY一个ENTITY的数据导出。谢谢。


Dear all,

经过从本周二开始的N轮测试,现将仍未解决的问题汇总如下。

1.表2-继续教育“education type"未带出;

2.表4-住房贷款- A.组合贷款仅导出了商业贷款合同号,合同号应为“商业贷款合同号& 公积金贷款合同号”;B.公积金贷款,未能带出合同编号。

3.表6-赡养老人-开发要求为:仅带出一条信息。区分如下情况:
- 对于父亲/母亲+/祖母/祖父/外祖母/外祖父的情况,Family
type带出1(即Parents)即可, Parent ID No. /Parent name/birth date带出父母任意一个人的信息,扣除金额是总扣除金额(如快照里父母两条,interface表单里只带一条即可,扣除金额2000);
-对于仅有祖母/祖父/外祖母/外祖父的情况,Parent ID type带出2 (即other legal dependents), Parent ID
No. /Parent name/birth date带出祖辈任意一个人的信息,扣除金额是总扣除金额(举例同上)。

4.Begin date区分如下情形设置,以elderly support表为例,假设员工是非独生子女。
A.假设员工4月份开始申报扣除2-4月份的。
*Begin/End Date (20190201/99991231)
*Only Child (Blank)
B.假设员工1月份开始申报扣除,1月份填写如下
*Begin/End Date
(20190101/99991231)
*Only Child (Blank)
2月份忘记申报,3月份申报2-3月份的 ,填写如下
*Begin/End Date (20190201/99991231)
*Only Child (Blank)

5.SAP系统要求导入到SAP的数据只能是每月数据,在interface表单中,elderly support表显示了扣除金额,如果出现3月份申报2-3月份的数据,则扣除金额会是两个月的金额,需要拆成单个月数据。例如,
员工一直每月扣除1000元赡养老人金,2月忘记申报,3月累计申报了2000元,Digi系统在3月会扣除2000,导出的数据也会是2000;那么在导入SAP系统时,系统只会认1000,不认2000,就会导入失败。

linux 测试环境搭建

安装后是v6.14.3

yum install -y nodejs
node -v

yum remove nodejs

https://npm.taobao.org/mirrors/node 中找需要的版本

手工 参考 https://blog.csdn.net/jonatha_n/article/details/75271050

/usr/local/目录中可能会需要root读写权限

cd /usr/local/
wget https://npm.taobao.org/mirrors/node/v8.12.0/node-v8.12.0-linux-x64.tar.gz

下载完成后解压

tar zxvf node-v8.12.0-linux-x64.tar.gz

重命名为node

mv node-v8.12.0-linux-x64 node

配置环境变量

vim /etc/profile

在最后边添加

#set for nodejs
export NODE_HOME=/usr/local/node
export PATH=$NODE_HOME/bin:$PATH

保存退出(:wq)执行命令是更改生效

source /etc/profile
node -v
npm -v

然后参考Iit#启动portal


yum install git 
git clone https://ling2:Wb191010610109@gitee.com/ling2/antd-mobile-test.git

常用代码

/**
	 * 获取当前机构下员工的人数
	 * 
	 * @param orgId
	 * @return
	 */
	public Integer getPersonNumOfOrg(String orgId) {
		AssertHelper.notEmpty_assert(orgId, "查询机构不能为空");
		ExtendDetachedCriteria criter = ExtendDetachedCriteria.forClass(BasePersonalInfo.class);
		criter.add(Restrictions.eq("orgId", orgId));

		criter.setProjection(Projections.count("basePersonalInfoUuid"));
		List list = this.findByCriteria(criter);
		Object value = list.size() > 0 ? list.get(0) : null;
		int num = value == null ? 0 : Integer.parseInt(value.toString());
		return num;
	}

	/**
	 * \获取机构下员工主键集合
	 * 
	 * @param orgId
	 * @return
	 */
	public List<String> getPersonIdsOfOrg(String orgId) {
		AssertHelper.notEmpty_assert(orgId, "查询机构不能为空");
		ExtendDetachedCriteria criteria = ExtendDetachedCriteria.forClass(BasePersonalInfo.class);
		criteria.add(Restrictions.eq("orgId", orgId));
		ProjectionList projList = Projections.projectionList();
		projList.add(Projections.property("basePersonalInfoUuid"));
		criteria.setProjection(projList);
		List list = this.findByCriteria(criteria);
		return list;
	}

	/**
	 * 获取机构下员工主键集合
	 * 
	 * @param orgId
	 * @param notInPersonIds 排除的员工
	 * @return
	 */
	public List<String> getPersonIdsOfOrg(String orgId, List<String> notInPersonIds) {
		AssertHelper.notEmpty_assert(orgId, "查询机构不能为空");
		ExtendDetachedCriteria criteria = ExtendDetachedCriteria.forClass(BasePersonalInfo.class);
		criteria.add(Restrictions.eq("orgId", orgId));
		criteria.add(Restrictions.not(Restrictions.in("basePersonalInfoUuid", notInPersonIds)));
		ProjectionList projList = Projections.projectionList();
		projList.add(Projections.property("basePersonalInfoUuid"));
		criteria.setProjection(projList)
		List list = this.findByCriteria(criteria);
		return list;
	}


/**
     * 获取某机构,某年,按月分组的申报金额合计
     * @param orgId
     * @param periodYear
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, BigDecimal> getDeductionMonthlySumAmountOfOrg(String orgId,int periodYear) throws Exception{
        List<IitDeductionType> deductionTypes = iitDeductionTypeService.findDeductionTypes();

        Map<String,BigDecimal> monthSumMap=new HashMap<>();
        monthSumMap.put("1",new BigDecimal(0));
        monthSumMap.put("2",new BigDecimal(0));
        monthSumMap.put("3",new BigDecimal(0));
        monthSumMap.put("4",new BigDecimal(0));
        monthSumMap.put("5",new BigDecimal(0));
        monthSumMap.put("6",new BigDecimal(0));
        monthSumMap.put("7",new BigDecimal(0));
        monthSumMap.put("8",new BigDecimal(0));
        monthSumMap.put("9",new BigDecimal(0));
        monthSumMap.put("10",new BigDecimal(0));
        monthSumMap.put("11",new BigDecimal(0));
        monthSumMap.put("12",new BigDecimal(0));
        for (IitDeductionType iitDeductionType : deductionTypes) {
            BaseDeductionTypeEnums enums = BaseDeductionTypeEnums.valueOf(iitDeductionType.getBaseDeductionType());
            ExtendDetachedCriteria criteria = getExtendDetachedCriteriaByType(enums);
            //某机构,某年,某类型,按月分组的金额
            criteria.createAlias("iitDeductionClaimH", "iitDeductionClaimH");
            criteria.add(Restrictions.eq("iitDeductionClaimH.periodYear",periodYear));
            criteria.add(Restrictions.eq("iitDeductionClaimH.orgId", orgId));
            ProjectionList projectionList= Projections.projectionList()
                    .add(Projections.sum("deductionAmount"))
                    .add(Projections.sum("adjustmentAmount"))
                    .add(Projections.groupProperty("iitDeductionClaimH.periodMonth"));
            criteria.setProjection(projectionList);
            List<Object[]> list = this.findByCriteria(criteria);
            for(Object[] item:list){
                String month=item[2].toString();
                BigDecimal deductionAmount=new BigDecimal(item[0].toString());
                BigDecimal adjustmentAmount=new BigDecimal(item[1].toString());
                BigDecimal monthSum=monthSumMap.get(month);
                if(monthSum==null){
                    monthSum=new BigDecimal(0);
                    monthSumMap.put(month,monthSum);
                }
                monthSum=monthSum.add(deductionAmount).subtract(adjustmentAmount);
                monthSumMap.put(month,monthSum);
            }
        }

        Map<String,BigDecimal> result=new HashMap<>();
        for(String month:monthSumMap.keySet()){
            if("1".equals(month)){
                result.put("January",monthSumMap.get(month));
            }
            if("2".equals(month)){
                result.put("February",monthSumMap.get(month));
            }
            if("3".equals(month)){
                result.put("March",monthSumMap.get(month));
            }
            if("4".equals(month)){
                result.put("April",monthSumMap.get(month));
            }
            if("5".equals(month)){
                result.put("May",monthSumMap.get(month));
            }
            if("6".equals(month)){
                result.put("June",monthSumMap.get(month));
            }
            if("7".equals(month)){
                result.put("July",monthSumMap.get(month));
            }
            if("8".equals(month)){
                result.put("August",monthSumMap.get(month));
            }
            if("9".equals(month)){
                result.put("September",monthSumMap.get(month));
            }
            if("10".equals(month)){
                result.put("October",monthSumMap.get(month));
            }
            if("11".equals(month)){
                result.put("November",monthSumMap.get(month));
            }
            if("12".equals(month)){
                result.put("December",monthSumMap.get(month));
            }
        }
        return result;
    }
    /**
     * 获取某机构,某年,按类型分组的申报金额合计
     * @param orgId
     * @param periodYear
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, BigDecimal> getDeductionTypeSumAmountOfOrg(String orgId,int periodYear) throws Exception{
        List<IitDeductionType> deductionTypes = iitDeductionTypeService.findDeductionTypes();

        Map<String,BigDecimal> typeSumMap=new HashMap<>();
        for (IitDeductionType iitDeductionType : deductionTypes) {
            BaseDeductionTypeEnums enums = BaseDeductionTypeEnums.valueOf(iitDeductionType.getBaseDeductionType());
            ExtendDetachedCriteria criteria = getExtendDetachedCriteriaByType(enums);
            //某机构,某年,某类型,按月分组的金额
            criteria.createAlias("iitDeductionClaimH", "iitDeductionClaimH");
            criteria.add(Restrictions.eq("iitDeductionClaimH.periodYear",periodYear));
            criteria.add(Restrictions.eq("iitDeductionClaimH.orgId", orgId));
            ProjectionList projectionList= Projections.projectionList()
                    .add(Projections.sum("deductionAmount"))
                    .add(Projections.sum("adjustmentAmount"));
            criteria.setProjection(projectionList);
            List<Object[]> list = this.findByCriteria(criteria);
            BigDecimal typeSum=new BigDecimal(0);
            for(Object[] item:list){
                BigDecimal deductionAmount=new BigDecimal(item[0].toString());
                BigDecimal adjustmentAmount=new BigDecimal(item[1].toString());
                typeSum=typeSum.add(deductionAmount).subtract(adjustmentAmount);
            }
            typeSumMap.put(iitDeductionType.getBaseDeductionType(),typeSum);
        }
        return typeSumMap;
    }

    private ExtendDetachedCriteria getExtendDetachedCriteriaByType(BaseDeductionTypeEnums enums) throws Exception {
        ExtendDetachedCriteria criteria;
        switch (enums) {
            case rental:// 房屋租金
                criteria = ExtendDetachedCriteria.forClass(IitDeductionClaimLRental.class);
                break;
            case elder:// 赡养老人
                criteria = ExtendDetachedCriteria.forClass(IitDeductionClaimLElder.class);
                break;
            case childEdu:// 子女教育
                criteria = ExtendDetachedCriteria.forClass(IitDeductionClaimLKid.class);
                break;
            case careerEdu:// 职业继续教育
                criteria = ExtendDetachedCriteria.forClass(IitDeductionClaimLCeCareer.class);
                break;
            case schoolEdu:// 学历继续教育
                criteria = ExtendDetachedCriteria.forClass(IitDeductionClaimLCeSchool.class);
                break;
            case loanInterest:// 贷款利息
                criteria = ExtendDetachedCriteria.forClass(IitDeductionClaimLLoan.class);
                break;
            default:
                throw new Exception("不支持的类型");
        }
        return criteria;
    }

问题解决

Module not found: Error: Can't resolve ng-zorro-antd.ngfactory

  • 不带@node-moudle
import { TranslateService } from '@ngx-translate/core';
  • ng-zorro-antd
import { NzNotificationService } from 'ng-zorro-antd';
  • xxx.module.ts中添加NgZorroAntdModule
imports: [SharedModule, PersoninfoModule,NgZorroAntdModule],
  • 不能使用tsconfig.app.json中配置短路径语法

Cannot read property 'nativeElement' of undefined

https://github.com/vaadin/vaadin-grid/issues/411

its raw version as part of a circular reference

@Lazy

G2.track(false)无效

主要是console中下面的错误导致的

g2.js:20934 There are multiple versions of G2. Version 3.3.4's reference is 'window.G2_3'
  • 去掉所有的import @antv引用
  • src\typings.d.ts(全局)中定义或src\app\core\startup\startup.service.ts(局部)中定义
declare var G2: any;
  • src\app\core\startup\startup.service.ts的构造函数中
 constructor{
......
//console.log(G2);
    if (typeof G2 !== 'undefined') G2.track(false);
......
}

readAsBinaryString ie11兼容性问题

https://stackoverflow.com/questions/31391207/javascript-readasbinarystring-function-on-e11

undefined is not an object (evaluating 'this.selectedTarget[o].currentY=-a.indexOf

TypeError: undefined is not an object (evaluating 'this.selectedTarget[o].currentY=-a.indexOf(this.resultArr[o])')
initRangeArr — main.5bfbd6d8a2ef1c37ad4a.js:9000:261
setCurrentSelected — main.5bfbd6d8a2ef1c37ad4a.js:8993
setCurrentSelected — main.5bfbd6d8a2ef1c37ad4a.js:8995
panend — main.5bfbd6d8a2ef1c37ad4a.js:8785:847
(匿名函数) — main.5bfbd6d8a2ef1c37ad4a.js:17058:374
pl — main.5bfbd6d8a2ef1c37ad4a.js:3769:105
(匿名函数) — main.5bfbd6d8a2ef1c37ad4a.js:12008
onInvokeTask — main.5bfbd6d8a2ef1c37ad4a.js:2630
runTask — polyfills.c6871e56cb80756a5498.js:124
invokeTask — polyfills.c6871e56cb80756a5498.js:260
k — polyfills.c6871e56cb80756a5498.js:833
m — polyfills.c6871e56cb80756a5498.js:844

Java Security: Illegal key size or default parameters?

https://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters

文件:Jce policy-8.zip

/**
* http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
* https://www.cnblogs.com/yaks/p/5608358.html
* Java几乎各种常用加密算法都能找到对应的实现。因为美国的出口限制,Sun通过权限文件(local_policy.jar、US_export_policy.jar)做了相应限制。因此存在一些问题:
* ●密钥长度上不能满足需求(如:java.security.InvalidKeyException: Illegal key size or default
* parameters); ●部分算法未能支持,如MD4、SHA-224等算法;
* ●API使用起来还不是很方便;一些常用的进制转换辅助工具未能提供,如Base64编码转换、十六进制编码转换等工具。
* Oracle在其官方网站上提供了无政策限制权限文件(Unlimited Strength Jurisdiction Policy
* Files),我们只需要将其部署在JRE环境中,就可以解决限制问题。
* 
* 解决方法:
* 
* http://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters
* 
* JDK8 jar包下载地址:
* 
* http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
* 
* 
* 
* 把$JAVA_HOME/jre/lib/security/policy/unlimited里面的两个jar包:local_policy.jar 和 US_export_policy.jar
* 替换掉原来jdk安装目录$JAVA_HOME\jre\lib\security 下的两个jar包接可以了
* 
*/