地铁行政办公交接文档
>i 一、集团行政办公
>i web端svn:http://221.6.30.202:8443/svn/shide/idea_bg_njdtob/bg_njdtob
>i 二、建设行政办公
>i web端svn:http://221.6.30.202:8443/svn/shide/idea_bg_jsoa/bg_jsob
>i 三、资源行政办公
>i web端svn:http://221.6.30.202:8443/svn/shide/idea_bg_njzyob
>i 四、宁高宁北行政办公
>i web端svn:http://221.6.30.202:8443/svn/shide/njdtngnbob/bg_gdjtob
>d 重要维护内容:
4个项目结构和业务基本一致,数据库连接配置位置application.properties

```java
db.default.url=jdbc\:oracle\:thin\:@192.168.1.29\:1521\:njmetro //测试库
#db.default.url=jdbc\:oracle\:thin\:@192.168.1.20\:1521\:njmetro //正式库
db.default.username=bg_njdtob
db.default.password=123
```
>d 数据库(正式环境):
4个项目数据库连接地址一致,登陆用户密码不同。
1、集团行政办公:用户:bg_njdtob 密码:123
2、建设行政办公:用户:bg_jsob 密码:123
3、资源行政办公:用户:bg_njdtzyob 密码:123
4、宁高宁北行政办公:用户:bg_gdjtob 密码:123
>d 修改附件盘符配置:
>d 短信机配置(宁高宁北行政办公没有短信机):

>d 品高工作流连接配置:
```java
//测试环境
URLe=http://192.168.106.41:7003/20/WFProxy/engine
URLd=http://192.168.106.41:7003/20/WFProxy/data
URLa=http://192.168.106.41:7003/20/WFProxy/alert
URLm=http://192.168.106.41:7003/20/WFProxy/my
URLVIEW=http://192.168.106.42:7778/workflow/flowchart
http://192.168.106.42:7778/workflow
//正式环境
URLe=http://osb.njmetro.com.cn:7003/20/WFProxy/engine
URLd=http://osb.njmetro.com.cn:7003/20/WFProxy/data
URLa=http://osb.njmetro.com.cn:7003/20/WFProxy/alert
URLm=http://osb.njmetro.com.cn:7003/20/WFProxy/my
URLVIEW=http://home.njmetro.com.cn/workflow/flowchart
```
>d 自动同步统一身份信息:同步组织架构、人员信息、组织人员关系三个方法,只需开启同步组织架构方法的定时器即可。
>d 门户单点登陆配置:测试和正式环境的配置url不同,对应配置不同环境放开不同的链接路径。

```java
/**
* 登录验证
*
* @param model
* @return
*/
@RequestMapping("init-login")
public String login(@RequestParam Map<String, Object> parameterMap,HttpServletRequest request,
Model model) {
String ssouserId =request.getHeader("OAM_REMOTE_USER");
ssouserId = ssouserId.toLowerCase();
String url = "";
System.out.println("ssouserId:"+ssouserId);
List<VUser> userList = vUserManager.findBy("logonName",
ssouserId);
if (userList.size() > 0) {
//url = "redirect:/home/go-home.do";
//url = "redirect:http://sw.njmetro.com.cn:8012/bg_njdtob/home/go-home.do"; //部署正式环境时打开
url = "redirect:http://192.168.106.42:7777/bg_njdtob/home/go-home.do";//部署测试环境时打开
VUser user = userList.get(0);
SysOrg o = sysOrgManager.findUniqueBy("orgUimsId",user.getOrguimsid());
if (o.getParentOrgUimsId().equals("45")){
user.setParentOrgId(o.getOrgName());
}else{
SysOrg o1 = sysOrgManager.findUniqueBy("orgUimsId",o.getParentOrgUimsId());
user.setParentOrgId(o1.getOrgName());
}
model.addAttribute("user_session", user);
} else {
url = "redirect:/login/go-login.do";
//url = "redirect:http://sw.njmetro.com.cn:8012/bg_njdtob/login/go-login.do";//部署正式环境时打开
url = "redirect:http://192.168.106.42:7777/bg_njdtob/login/go-login.do";//部署测试环境时打开
}
return url;
}
```
>d 特殊维护内容:
1、集团行政办公:业财用印模块已对接了合同与固资系统,特殊原因目前暂停了对接,已开发好的内容在控制类PrintUseController中

主要逻辑:业财系统推送已在他们系统中流转完成的流程进入行政办公系统,由办公室进行后续的审批,推送进入行政办公系统的流程按照接口参数形成表单数据并且自动启动用印流程流转给办公室,办公室选择同意或不同意触发接口推送办理结果返回业财系统。
提供给业财系统调用的流程推送方法:
```java
/**
* 表单保存-业财接口
* @param parameterMap
* 前台传来的参数MAP
* @param attachmentIds
* 附件的ID(以逗号分隔的字符串)
* @param user
* 当前登录用户
* @return 保存是否成功的json
*/
@Transactional(rollbackFor={Exception.class})
@RequestMapping(value = "print-save-interface", method = RequestMethod.POST, produces = "application/json")
public @ResponseBody
Map<String, Object> printSaveForInterface(String attachmentIds, BdPrintApply promobj,HttpServletRequest request,
@RequestParam Map<String, Object> parameterMap) {
System.out.println("进入业财接口保存:");
Map<String, Object> resMap = new HashMap<String, Object>();
String statusCode = "200", message = "提交成功";
String fileList = "";
String result ="";
try {
result =readRaw(request.getInputStream());
try{
System.out.println("raw:"+result);
JSONObject obj = JSONObject.parseObject(result);
JSONObject dataObj = JSONObject.parseObject(obj.getString("data"));
promobj = JSONObject.toJavaObject(dataObj,BdPrintApply.class);
if(obj.get("fileList")!=null){
fileList = obj.getString("fileList");
}
if(promobj.getPrintName()!=null&&promobj.getPrintName().length()>0&&promobj.getFileCount()!=null&&promobj.getFileCount().length()>0
&&promobj.getSealnumber()!=null&&promobj.getSealnumber().length()>0&&promobj.getInterfaceId()!=null&&promobj.getInterfaceId().length()>0
&&promobj.getInterfaceType()!=null&&promobj.getInterfaceType().length()>0&&promobj.getApplyDate()!=null&&promobj.getTitle()!=null&&promobj.getTitle().length()>0
&&promobj.getCreateUserId()!=null&&promobj.getCreateUserId().length()>0&&promobj.getCreateUserName()!=null&&promobj.getCreateUserName().length()>0
&&promobj.getCreateOrgId()!=null&&promobj.getCreateOrgId().length()>0&&promobj.getCreateOrgName()!=null&&promobj.getCreateOrgName().length()>0){
BdPrintApply oldEntity = bdPrintApplyManager.findUniqueBy("interfaceId", promobj.getInterfaceId());
if(oldEntity!=null){
beanMapper.copy(promobj, oldEntity);
try {
bdPrintApplyManager.save(promobj);
statusCode = "200";
message = "interfaceId已存在,更新成功";
}catch (Exception e){
statusCode = "300";
message = "数据库保存失败";
}
}else{
try{
String printUseNo = "";
//从后台取出用印最新编号
BdPrintUseNo bdPrintUseNo = bdPrintUseNoManager.findUniqueBy("dataStatus", "1");
BdPrintUseNo newBdPrintUseNo = new BdPrintUseNo();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
String currentYear = sdf.format(new Date());
String useNo = "00001";
if(bdPrintUseNo == null){
printUseNo = currentYear + "00001";
}else{
if(currentYear.equals(bdPrintUseNo.getCurrentYear())){
Integer oldNo = Integer.valueOf(bdPrintUseNo.getPrintUseFullNo());
printUseNo = String.valueOf((oldNo + 1));
useNo = printUseNo.substring(4);
}else{
printUseNo = currentYear + "00001";
}
// 去除原编号状态
bdPrintUseNo.setDataStatus("");
bdPrintUseNoManager.save(bdPrintUseNo);
}
SimpleDateFormat y = new SimpleDateFormat("YYYY");
SimpleDateFormat m = new SimpleDateFormat("M");
promobj.setApplyYear(y.format(promobj.getApplyDate()));
promobj.setApplyMonth(m.format(promobj.getApplyDate()));
bdPrintApplyManager.save(promobj);
newBdPrintUseNo.setRowId(null);
newBdPrintUseNo.setRelationId(promobj.getRowId());
newBdPrintUseNo.setPrintUseFullNo(printUseNo);
newBdPrintUseNo.setCurrentYear(currentYear);
newBdPrintUseNo.setPrintUseNo(useNo);
newBdPrintUseNo.setDataStatus("1");
bdPrintUseNoManager.save(newBdPrintUseNo);
promobj.setContractNumber(printUseNo);
/*ChannelSftp cs = null;*/
try {
//cs = sftpConnection("ip", 8080, "账号", "密码");
try {
JSONArray fileArray = JSONArray.parseArray(fileList);
for (int f=0;f<fileArray.size();f++){
YcPrintFile file = JSONObject.toJavaObject(fileArray.getJSONObject(f),YcPrintFile.class);
file.setInterfaceId(promobj.getInterfaceId());
file.setTableId(promobj.getRowId());
file.setPiid(promobj.getPiid());
//downSftpFile(cs, file.getFileName(), file.getFilePath(), file.getSaveName(),fj);
//file.setFileLocalPath(fj + file.getSaveName());
ycPrintFileManager.save(file);
}
try{//启动流程
ProcessController pcent = new ProcessController();
VUser user = vUserManager.findUniqueBy("logonName",promobj.getCreateUserId());
ProcessResultVo resu = pcent.firstRunProcessYc(user);
System.out.println(resu);
promobj.setPiid(resu.getProcessInstId());
promobj.setBusinessKey(resu.getBusinessKey());
promobj.setPtid(resu.getProcessKey());
promobj.setActId("1");
bdPrintApplyManager.save(promobj);
statusCode = "200";
message = "保存成功";
}catch (Exception e){
e.printStackTrace();
statusCode = "300";
message = "流程启动失败";
}
}catch (Exception e){
e.printStackTrace();
statusCode = "300";
message = "附件类保存失败";
}finally {
}
}catch (Exception e){
e.printStackTrace();
statusCode = "300";
message = "ftp登陆失败";
}
}catch (Exception e){
statusCode = "300";
message = "数据库保存失败";
}
}
}else{
statusCode = "300";
message = "参数不完整";
}
}catch (Exception e){
statusCode = "300";
message = "实体类转换失败";
}
}catch (Exception e){
e.printStackTrace();
statusCode = "300";
message = "raw解析失败";
}
resMap.put("statusCode", statusCode);
resMap.put("message", message);
return resMap;
}
```
>d 提供给业财系统调用的推送审批意见接口:
```java
@RequestMapping(value = "print-interface-advice", method = RequestMethod.POST, produces = "application/json")
public @ResponseBody
Map<String, Object> printInterfaceAdvice(String attachmentIds, ProcAdviceStrategy promobj,HttpServletRequest request,
@RequestParam Map<String, Object> parameterMap) {
System.out.println("进入业财审批保存:");
Map<String, Object> resMap = new HashMap<String, Object>();
String statusCode = "200", message = "提交成功";
BdPrintApply beanDest = null;
String result ="";
Map<String,Object> params = new HashMap<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
try {
result =readRaw(request.getInputStream());
}catch (Exception e){
e.printStackTrace();
statusCode = "300";
message = "raw解析失败";
}
try{
System.out.println("raw:"+result);
JSONObject obj = JSONObject.parseObject(result);
if(obj.get("interfaceId")!=null){
BdPrintApply printBean = bdPrintApplyManager.findUniqueBy("interfaceId", obj.get("interfaceId").toString());
if(printBean!=null){
try{
JSONArray dataArray = JSONArray.parseArray(obj.get("adviceList").toString());
System.out.println("array:"+dataArray);
for (int i=0;i<dataArray.size();i++){
JSONObject inObj = dataArray.getJSONObject(i);
ProcAdviceInterface procAdvice = new ProcAdviceInterface();
procAdvice.setTableName(printBean.getBusinessKey());
procAdvice.setTableId(printBean.getRowId());
procAdvice.setPiid(printBean.getPiid());
procAdvice.setAiid(inObj.get("aiid").toString());
procAdvice.setAdviceContent(inObj.get("adviceContent").toString());
procAdvice.setFillTime(sdf.parse(inObj.get("createTime").toString()));
//procAdvice.setFillUserName(inObj.get("fillUserName").toString());
procAdvice.setCreateTime(sdf.parse(inObj.get("createTime").toString()));
procAdvice.setPtid(printBean.getPtid());
procAdvice.setCurrentActName(inObj.get("currentActname").toString());
procAdvice.setDocType("0");
procAdvice.setCreatorUsername(inObj.get("createUserName").toString());
procAdvice.setCreatorUserId(inObj.get("createUserId").toString());
procAdviceInterfaceManager.save(procAdvice);
/* ProcSignature procStr = new ProcSignature();
procStr.setCreatorId(inObj.get("createUserId").toString());
procStr.setCreateTime(sdf.parse(inObj.get("createTime").toString()));
procStr.setCreatorName(inObj.get("createUserName").toString());
if(inObj.get("currentActname").toString().equals("部门负责人审核")){
procStr.setControlName("bmfzrsh");
}else if(inObj.get("currentActname").toString().equals("分管领导审批")){
procStr.setControlName("fgldsp");
}else{
procStr.setControlName("");
}
procStr.setOptionContext(inObj.get("adviceContent").toString());
procStr.setTableId(printBean.getRowId());
procStr.setDeleted("0");
procStr.setPiid(printBean.getPiid());
oaSignatureManager.save(procStr);*/
}
statusCode = "200";
message = "保存成功";
}catch (Exception e){
e.printStackTrace();
statusCode = "300";
message = "审批过程保存失败";
}
}else{
statusCode = "300";
message = "未查询到对应主键申请单";
}
}else{
statusCode = "300";
message = "缺少主键Id";
}
}catch (Exception e){
statusCode = "300";
message = "实体类转换失败";
}
resMap.put("statusCode", statusCode);
resMap.put("message", message);
//resMap.put("data",userlist);
return resMap;
}
```
>d 办公室办理后反馈办理结果推送给业财:
调用业财的接口前需先获取token,调用token的方法在utils文件夹中

业财各个系统的反馈地址不同,配置在静态文件中:

>d 2、建设行政办公:建设公司有抢会议室的需求,所以对建设公司的会议室占用模块有特殊处理,在进入选择会议室窗口时,数据库会记录访问时间,当多个人同时选择同一个会议室时,系统会将会议室分配给最早打开选择窗口的用户,其他用户则会提示等待或者已被占用,系统定时器每分钟扫描访问记录表,当一个用户打开选择窗口超过3分钟未发起会议室申请,系统会清除该用户的访问记录,该会议室的占用权限会交给顺位的下一个用户,以此类推。
定时器位置:

```java
/**
* 删除超时会议室
* */
@Scheduled(cron = "0 0/1 * * * ?")
public void removeTimeOutMeetingroom() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
List<MeetingRoomList> meetList = meetingRoomListManager.getAll();
for (MeetingRoomList meet:
meetList ) {
long updateTime = meet.getApplyDate().getTime();
long currentTime =System.currentTimeMillis();
long diff=(currentTime-updateTime)/1000/60;
if(diff>=1){
meetingRoomListManager.remove(meet);
}
}
System.out.println("已清除超时会议室申请!——》"+sdf.format(new Date()));
}
```
>d 部署操作:
连接地铁VPN,访问堡垒机地址:https://192.168.103.22/
1、集团行政办公/建设行政办公:堡垒机账号:gaoxin 密码:GaoXinMetroBlj@321
测试服务器ip:192.168.106.44
正式服务器ip(2台,都需要部署):192.168.1.8,192.168.1.9
2、资源行政办公:堡垒机账号:gaoxin_zy 密码:Gaoxin_zy123
测试服务器与上文集团/建设行政办公测试服务器一致
正式服务器ip:192.168.4.196
3、宁高宁北行政办公:堡垒机账号:gaoxin2 密码:GAOXIN123
4、驾驶舱数据接口部署位置:堡垒机账号:gaoxinceshi 密码:12qw!@QW
服务器ip:192.168.106.45
