Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yuyiAdminServer
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
node_server
yuyiAdminServer
Commits
936cbd63
Commit
936cbd63
authored
Jan 27, 2026
by
chenjinjing
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
no message
parent
5e699372
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
1341 additions
and
2285 deletions
+1341
-2285
createZip copy.ts
src/biz/createZip copy.ts
+0
-2227
ledger.ts
src/biz/ledger.ts
+15
-1
mail.ts
src/biz/mail.ts
+2
-2
ruFu.ts
src/biz/ruFu.ts
+1205
-37
zaiFu.ts
src/biz/zaiFu.ts
+73
-2
enum.ts
src/config/enum/enum.ts
+2
-1
errorEnum.ts
src/config/enum/errorEnum.ts
+2
-1
main.ts
src/main.ts
+1
-1
admin.ts
src/routers/admin.ts
+34
-5
ledger.ts
src/routers/ledger.ts
+2
-2
userRuFu.ts
src/routers/userRuFu.ts
+5
-6
No files found.
src/biz/createZip copy.ts
deleted
100644 → 0
View file @
5e699372
import
{
ERRORENUM
}
from
"../config/enum/errorEnum"
;
import
{
BizError
}
from
"../util/bizError"
;
import
*
as
archiver
from
'archiver'
;
import
*
as
fs
from
'fs-extra'
;
import
*
as
path
from
'path'
;
import
*
as
ExcelJS
from
'exceljs'
;
import
{
selectData
,
selectManyTableData
}
from
"../data/operationalData"
;
import
{
OPERATIONALDATATYPE
,
TABLENAME
}
from
"../config/enum/dbEnum"
;
import
{
getAllDwOutPut
}
from
'./zaiFu'
;
import
*
as
enumConfig
from
"../config/enum/enum"
;
import
{
changeAdd
}
from
"../util/piecemeal"
;
import
{
getMySqlMs
}
from
"../tools/system"
;
const
moment
=
require
(
"moment"
);
const
fetch
=
require
(
'node-fetch'
);
export
async
function
newDow
(
eIds
,
options
)
{
/**拼excel表格数据 */
let
selectParam
:
any
=
{
// state: enumConfig.CHANGESTATE.已通过,
eId
:
{
"%in%"
:
eIds
}
// 只查询选中的企业
};
// 主表字段
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"logonAddress"
,
"qiYeGuiMo"
];
let
manyTableInfo
:
any
=
{};
// let rufuSelectParam = { state: { "%between%": [enumConfig.FUHUASTATE.实体孵化, enumConfig.FUHUASTATE.虚拟孵化] } };
manyTableInfo
[
TABLENAME
.
企业孵化信息
]
=
{
column
:
[
"moveOutTime"
,
"moveOutType"
,
"startTime"
,
"endTime"
],
where
:
{}
};
// 执行多表联查
let
resInfo
=
await
selectManyTableData
(
OPERATIONALDATATYPE
.
多表联查
,
TABLENAME
.
企业基础信息表
,
selectParam
,
filesList
,
manyTableInfo
);
/**查询租赁表信息 */
let
leaseWhere
:
any
=
{
eId
:
{
"%in%"
:
eIds
}
};
let
zuLingList
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
TABLENAME
.
租赁信息
,
leaseWhere
,
[
"eId"
,
"area"
,
"startTime"
,
"endTime"
,
"building"
,
"roomNumber"
]);
let
zaifuMap
=
{};
if
(
zuLingList
.
length
)
{
zuLingList
.
forEach
(
info
=>
{
zaifuMap
[
info
.
eId
]
=
info
;
});
}
let
titleConfig
=
[
{
typeName
:
'基础信息'
,
keyList
:[
{
key
:
'企业名称'
,
value
:
'enterpriseName'
},
{
key
:
'统一信用代码'
,
value
:
'uscc'
},
{
key
:
'注册时间'
,
value
:
'logonTime'
},
{
key
:
'行业领域'
,
value
:
'industry'
},
{
key
:
'注册地址'
,
value
:
'logonAddress'
},
{
key
:
'联系人'
,
value
:
'liaison'
},
{
key
:
'联系电话'
,
value
:
'liaisonPhone'
},
{
key
:
'企业规模'
,
value
:
'qiYeGuiMo'
},
{
key
:
'实缴资本'
,
value
:
'shijiaoziben'
},
{
key
:
'简介'
,
value
:
'jianJie'
},
{
key
:
'注册资本'
,
value
:
'zhuceziben'
},
{
key
:
'经营地址'
,
value
:
'operatingAddress'
},
{
key
:
'经营范围'
,
value
:
'jingYingFanWei'
},
{
key
:
'孵化时间'
,
value
:
'fuhuaTime'
},
{
key
:
'租赁面积'
,
value
:
'area'
},
{
key
:
'楼号'
,
value
:
'building'
},
{
key
:
'室号'
,
value
:
'roomNumber'
}
]
},
{
typeName
:
'经营数据'
,
keyList
:[
{
key
:
'营收(万元)'
,
value
:
'BI'
},
{
key
:
'纳税(万元)'
,
value
:
'TXP'
},
{
key
:
'研发投入(万元)'
,
value
:
'RD'
},
{
key
:
'年度'
,
value
:
'annual'
},
{
key
:
'季度'
,
value
:
'quarter'
}
]
},
{
typeName
:
'融资情况'
,
keyList
:[
{
key
:
'融资金额(万元)'
,
value
:
'financingAmount'
},
{
key
:
'融资轮次'
,
value
:
'financingRounds'
},
{
key
:
'孵化器是否参与投资'
,
value
:
'fuHuaQiInvestment'
},
{
key
:
'孵化器投资方式'
,
value
:
'fuHuaQiInvestmentStyle'
},
{
key
:
'孵化器投资金额'
,
value
:
'fuHuaQiInvestmentAmount'
},
{
key
:
'获得投资时间'
,
value
:
'investmentDate'
},
{
key
:
'投资机构名称'
,
value
:
'investmentInstitutionsName'
},
{
key
:
'估值'
,
value
:
'valuation'
},
]
},{
typeName
:
'荣誉奖项'
,
keyList
:[
{
key
:
'荣誉奖项数量'
,
value
:
'awardCount'
},
// { key: '奖项名称', value: 'awardName' },
// { key: '颁奖单位', value: 'awardingUnit' },
// { key: '获奖日期', value: 'awardTime' },
// { key: '奖项等级', value: 'awardLevel' }
]
}
];
let
titleList
=
[];
//拼接表头
for
(
let
i
=
0
;
i
<
titleConfig
[
0
].
keyList
.
length
;
i
++
)
{
titleList
.
push
(
titleConfig
[
0
].
keyList
[
i
].
key
);
}
let
dataList
=
[];
//结构:[{eId:"", subList:[数据...]}]
//拼接基础信息
let
enterpriseNameMap
=
{};
//用来给文件目录映射名称用 {eId:"名称"}
for
(
let
info
of
resInfo
)
{
let
{
eId
,
enterpriseName
,
uscc
,
logonTime
,
logonAddress
,
qiYeGuiMo
,
enterprise_fuhuas
}
=
info
;
enterpriseNameMap
[
eId
]
=
enterpriseName
;
let
leasesTime
=
'-'
;
if
(
zaifuMap
[
eId
]?.
startTime
)
{
leasesTime
=
`
${
moment
(
zaifuMap
[
eId
].
startTime
).
format
(
"YYYY-MM-DD"
)}
至
${
moment
(
zaifuMap
[
eId
].
endTime
).
format
(
"YYYY-MM-DD"
)}
`
;
}
let
fuhuaTime
=
'-'
;
if
(
enterprise_fuhuas
[
0
]?.
startTime
)
{
fuhuaTime
=
`
${
moment
(
enterprise_fuhuas
[
0
].
startTime
).
format
(
"YYYY-MM-DD"
)}
至
${
moment
(
enterprise_fuhuas
[
0
].
endTime
).
format
(
"YYYY-MM-DD"
)}
`
;
}
let
itemData
=
{
eId
,
enterpriseName
,
uscc
,
logonTime
:
moment
(
logonTime
).
format
(
"YYYY-MM-DD"
),
logonAddress
:
changeAdd
(
JSON
.
parse
(
logonAddress
)),
qiYeGuiMo
,
fuhuaTime
,
leasesTime
,
area
:
zaifuMap
[
eId
]?.
area
?
`
${
zaifuMap
[
eId
].
area
}
㎡`
:
'-'
,
building
:
zaifuMap
[
eId
]?.
building
||
'-'
,
roomNumber
:
zaifuMap
[
eId
]?.
roomNumber
||
'-'
}
let
subList
=
[];
for
(
let
i
=
0
;
i
<
titleConfig
[
0
].
keyList
.
length
;
i
++
)
{
subList
.
push
(
itemData
[
titleConfig
[
0
].
keyList
[
i
].
value
]
||
""
);
}
dataList
.
push
({
eId
,
subList
});
}
//拼接第经营数据 写法参考第一个拼接基础信息,但是需要注意的是,赋值的时候不能使用excelDataList.push(), 要用下标赋值,做到这里的时候来问我
/**查询经营表信息 */
let
jinyingWhere
:
any
=
{
eId
:
{
"%in%"
:
eIds
},
isSubmit
:
enumConfig
.
STATE
.
是
};
let
jinyingList
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
TABLENAME
.
企业经营信息
,
jinyingWhere
,
[
"eId"
,
"annual"
,
"quarter"
,
"BI"
,
"TXP"
,
"RD"
,
"createTime"
]);
// 根据年度季度获取最新一条已提交经营数据 // a.1 b.1 a.2 c.1
let
jinyingListToTimeMap
:
any
=
{};
jinyingList
.
forEach
(
info
=>
{
let
{
eId
}
=
info
;
if
(
!
jinyingListToTimeMap
[
eId
])
jinyingListToTimeMap
[
eId
]
=
[];
jinyingListToTimeMap
[
eId
].
push
(
info
);
});
let
jinyingMap
=
{};
//结构:{"eId":数据字段}
for
(
let
eId
in
jinyingListToTimeMap
)
{
let
thisEidJinyingList
=
jinyingListToTimeMap
[
eId
];
thisEidJinyingList
.
sort
((
a
,
b
)
=>
{
//先按年度比较
if
(
b
.
annual
!==
a
.
annual
)
{
return
new
Date
(
b
.
annual
).
valueOf
()
-
new
Date
(
a
.
annual
).
valueOf
();
}
//年度相同则按季度比较
return
b
.
quarter
-
a
.
quarter
;
});
//将数据进行格式化:枚举转换 时间格式转换
let
thisjingyinInfo
=
thisEidJinyingList
[
0
];
thisjingyinInfo
.
quarter
=
changeEnumValue
(
enumConfig
.
QUARTER
,
thisjingyinInfo
.
quarter
);
thisjingyinInfo
.
annual
=
moment
(
thisjingyinInfo
.
annual
).
format
(
"YYYY"
);
jinyingMap
[
eId
]
=
thisjingyinInfo
;
}
//拼接经营数据的表头
for
(
let
i
=
0
;
i
<
titleConfig
[
1
].
keyList
.
length
;
i
++
)
{
titleList
.
push
(
titleConfig
[
1
].
keyList
[
i
].
key
);
}
for
(
let
i
=
0
;
i
<
dataList
.
length
;
i
++
)
{
let
{
eId
,
subList
}
=
dataList
[
i
];
for
(
let
i
=
0
;
i
<
titleConfig
[
1
].
keyList
.
length
;
i
++
)
{
//取经营数据的配置 按配置将jinyinMap的数据映射到 subList
if
(
!
jinyingMap
[
eId
])
{
subList
.
push
(
""
);
}
else
{
subList
.
push
(
jinyingMap
[
eId
][
titleConfig
[
1
].
keyList
[
i
].
value
]
||
""
);
}
}
}
/**查询融资信息 拼接融资信息 同上注释*/
let
rongziWhere
:
any
=
{
eId
:
{
"%in%"
:
eIds
}
};
let
rongziColumn
=
[
"eId"
,
"financingAmount"
,
"financingRounds"
,
"fuHuaQiInvestment"
,
"fuHuaQiInvestmentStyle"
,
"fuHuaQiInvestmentAmount"
,
"investmentDate"
,
"investmentInstitutionsName"
,
"valuation"
];
let
rongziList
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
TABLENAME
.
企业融资
,
rongziWhere
,
rongziColumn
);
// 根据获得投资时间获取最新一条数据
let
rongziListToTimeMap
:
any
=
{};
rongziList
.
forEach
(
info
=>
{
let
{
eId
}
=
info
;
if
(
!
rongziListToTimeMap
[
eId
])
rongziListToTimeMap
[
eId
]
=
[];
rongziListToTimeMap
[
eId
].
push
(
info
);
});
let
rongziMap
=
{};
for
(
let
eId
in
rongziListToTimeMap
)
{
let
thisEidRongZiList
=
rongziListToTimeMap
[
eId
];
thisEidRongZiList
.
sort
((
a
,
b
)
=>
{
return
new
Date
(
b
.
investmentDate
).
valueOf
()
-
new
Date
(
a
.
investmentDate
).
valueOf
();
})
//将数据格式化
let
thisRongZiInfo
=
thisEidRongZiList
[
0
];
thisRongZiInfo
.
financingRounds
=
changeEnumValue
(
enumConfig
.
FINANCINGROUNDS
,
thisRongZiInfo
.
financingRounds
);
thisRongZiInfo
.
fuHuaQiInvestmentStyle
=
changeEnumValue
(
enumConfig
.
FUHUAQILNVESTMENTSTYLE
,
thisRongZiInfo
.
fuHuaQiInvestmentStyle
);
thisRongZiInfo
.
investmentDate
=
moment
(
thisRongZiInfo
.
investmentDate
).
format
(
"YYYY-MM-DD"
);
rongziMap
[
eId
]
=
thisRongZiInfo
;
}
//拼接融资数据的表头
for
(
let
i
=
0
;
i
<
titleConfig
[
2
].
keyList
.
length
;
i
++
)
{
titleList
.
push
(
titleConfig
[
2
].
keyList
[
i
].
key
);
}
for
(
let
i
=
0
;
i
<
dataList
.
length
;
i
++
)
{
let
{
eId
,
subList
}
=
dataList
[
i
];
for
(
let
i
=
0
;
i
<
titleConfig
[
2
].
keyList
.
length
;
i
++
)
{
//取融资数据的配置 按配置将rongziMap的数据映射到 subList
if
(
!
rongziMap
[
eId
])
{
subList
.
push
(
""
);
}
else
{
subList
.
push
(
rongziMap
[
eId
][
titleConfig
[
2
].
keyList
[
i
].
value
]
||
""
);
}
}
}
/**查询荣誉奖项信息 拼接荣誉奖项信息 同上注释*/
let
rongyuWhere
:
any
=
{
eId
:
{
"%in%"
:
eIds
}};
let
rongyuList
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
TABLENAME
.
企业荣誉
,
rongyuWhere
,
[
"eId"
,
"awardName"
,
"awardingUnit"
,
"awardTime"
,
"awardLevel"
]);
//统计荣誉奖项数量
let
rongyuMap
=
{}
if
(
rongyuList
.
length
)
{
rongyuList
.
forEach
(
info
=>
{
let
{
eId
}
=
info
;
if
(
!
rongyuMap
[
eId
])
rongyuMap
[
eId
]
=
{
"awardCount"
:
0
};
else
rongyuMap
[
eId
][
"awardCount"
]
+=
1
;
});
}
else
{
for
(
let
i
=
0
;
i
<
eIds
.
length
;
i
++
)
{
if
(
!
rongyuMap
[
eIds
[
i
]])
rongyuMap
[
eIds
[
i
]]
=
{
"awardCount"
:
0
};
else
rongyuMap
[
eIds
[
i
]][
"awardCount"
]
+=
1
;
}
}
//拼接荣誉奖项的表头
for
(
let
i
=
0
;
i
<
titleConfig
[
3
].
keyList
.
length
;
i
++
)
{
titleList
.
push
(
titleConfig
[
3
].
keyList
[
i
].
key
);
}
for
(
let
i
=
0
;
i
<
dataList
.
length
;
i
++
)
{
let
{
eId
,
subList
}
=
dataList
[
i
];
for
(
let
i
=
0
;
i
<
titleConfig
[
3
].
keyList
.
length
;
i
++
)
{
//取荣誉奖项的配置 按配置将rongyuMap的数据映射到 subList
subList
.
push
(
rongyuMap
[
eId
][
titleConfig
[
3
].
keyList
[
i
].
value
||
""
]);
}
}
//得到了excelDataList列表
let
excelDataList
=
[
titleList
];
//[[标题...],[数据...]]
dataList
.
forEach
(
info
=>
{
let
{
eId
,
subList
}
=
info
;
excelDataList
.
push
(
subList
);
});
/**接下来要获取对应的文件目录 */
console
.
log
();
//1.首先要知道要获取一些什么文件 商标=>字段
let
getFilesConf
=
{};
//如果无需使用库中的命名,就用中文
getFilesConf
[
DOWNLOADTYPE
.
知识产权
]
=
{
cheName
:
"知识产权"
,
itemConfList
:[
{
tableName
:
TABLENAME
.
专利
,
filesConfMap
:{
"iprUrl"
:
"title"
}},
{
tableName
:
TABLENAME
.
软件著作权
,
filesConfMap
:{
"iprUrl"
:
"name"
}},
{
tableName
:
TABLENAME
.
作品著作权
,
filesConfMap
:{
"iprUrl"
:
"name"
}},
{
tableName
:
TABLENAME
.
商标
,
filesConfMap
:{
"imageUrl"
:
"name"
}}
]
};
getFilesConf
[
DOWNLOADTYPE
.
租赁信息
]
=
{
cheName
:
"租赁信息"
,
itemConfList
:[{
tableName
:
TABLENAME
.
租赁信息
,
filesConfMap
:{
"sanFangXieYi"
:
"三方协议"
,
"fuHuaXieYi"
:
"孵化协议"
,
"fangWuZuLing"
:
"房屋租赁合同"
,
"fuHuaXieYiBuChong"
:
"孵化协议补充协议书"
,
"chengXinChengNuoHan"
:
"诚信承诺函"
,
"yingYeZhiZhao"
:
"营业执照复印件"
,
"ruFuZiLiao"
:
"入孵资料明细"
,
"ruZhuJiHua"
:
"入驻计划复印件"
,
"yaJinZhiFu"
:
"押金支付凭证"
,
"cardCopy"
:
"身份证复印件地址"
,
}}]
};
getFilesConf
[
DOWNLOADTYPE
.
资质证书
]
=
{
cheName
:
"资质证书"
,
itemConfList
:[{
tableName
:
TABLENAME
.
企业资质
,
filesConfMap
:{
"kxImg"
:
"科技型中小企业证书"
,
"gaoXinJiShuImg"
:
"高新技术证书"
,
"zjtxImg"
:
"专精特新证书"
,
"xjrPyImg"
:
"小巨人培育证书"
,
"cxImg"
:
"创新型中小企业证书"
,
}}]
};
//2.拼接成 filesServer 需要的数据结构
let
filesServerFileList
=
[];
//[ {enterpriseName:"", thisEnterpriseFilesList:[{dirName:"商标", subList:[{fileName:"商标名1", url:"" }] }, {}] }]
let
enterpriseFilesMap
=
{};
//{"企业名称":{"商标", subList:[{fileName:"商标名1", url:"" }]} }
for
(
let
dowType
in
getFilesConf
)
{
let
{
itemConfList
,
cheName
}
=
getFilesConf
[
dowType
];
for
(
let
i
=
0
;
i
<
itemConfList
.
length
;
i
++
)
{
let
{
tableName
,
filesConfMap
}
=
itemConfList
[
i
];
let
itemSelectFiles
=
[
"eId"
];
for
(
let
filesConfKey
in
filesConfMap
)
{
if
(
/^
[
A-Za-z
]
+$/
.
test
(
filesConfMap
[
filesConfKey
]))
{
itemSelectFiles
.
push
(
filesConfMap
[
filesConfKey
]);
}
itemSelectFiles
.
push
(
filesConfKey
);
}
let
itemDBList
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
tableName
,
{
eId
:
{
"%in%"
:
eIds
}},
itemSelectFiles
);
itemDBList
.
forEach
(
info
=>
{
//多个企业的待会在这里做判断 用名称做区分
if
(
!
enterpriseFilesMap
[
info
.
eId
])
enterpriseFilesMap
[
info
.
eId
]
=
{};
if
(
!
enterpriseFilesMap
[
info
.
eId
][
cheName
])
enterpriseFilesMap
[
info
.
eId
][
cheName
]
=
[];
for
(
let
filesConfKey
in
filesConfMap
)
{
// url:名称
let
infofileName
=
filesConfMap
[
filesConfKey
];
if
(
/^
[
A-Za-z
]
+$/
.
test
(
infofileName
))
{
infofileName
=
info
[
infofileName
];
}
let
thisInfoFileUrlList
=
[];
if
(
info
[
filesConfKey
])
{
thisInfoFileUrlList
=
JSON
.
parse
(
info
[
filesConfKey
])
}
thisInfoFileUrlList
.
forEach
((
subFileUrl
,
subFileUrlIndex
)
=>
{
let
subFileName
=
infofileName
;
if
(
subFileUrlIndex
)
{
subFileName
+=
`_
${
subFileUrlIndex
+
1
}
`
;
}
enterpriseFilesMap
[
info
.
eId
][
cheName
].
push
({
fileName
:
subFileName
,
url
:
subFileUrl
});
})
}
});
}
}
//[ {enterpriseName:"", thisEnterpriseFilesList:[{dirName:"商标", subList:[{fileName:"商标名1", url:"" }] }, {}] }]
for
(
let
eId
in
enterpriseFilesMap
)
{
let
thisEnterpriseFilesList
=
[];
for
(
let
cheName
in
enterpriseFilesMap
[
eId
])
{
let
subList
=
enterpriseFilesMap
[
eId
][
cheName
];
thisEnterpriseFilesList
.
push
({
dirName
:
cheName
,
subList
});
}
filesServerFileList
.
push
({
enterpriseName
:
enterpriseNameMap
[
eId
],
thisEnterpriseFilesList
});
}
let
reqData
=
{
excelDataList
:{
name
:
"sheet1"
,
data
:
excelDataList
},
//{ name:"sheet1", data:[[]]} ];
fileList
:
filesServerFileList
,
zipFileName
:
`企业数据合并_
${
eIds
.
length
}
家_
${
moment
().
format
(
'YYYYMMDDHHmmss'
)}
`
};
let
fileReqRes
=
await
post
(
`
${
systemConfig
.
unZipFileUrl
}
/file/admin/zipdownload/consolidated`
,
reqData
,
{
sign
:
"isdfalfdjasoiufoisjdlnad29230428029014i23mlkdslkf"
});
return
fileReqRes
;
}
/**
* 下载选中企业的zip包文件(最多10个)- 直接包含文件夹版本
*/
export
async
function
downloadSelectedEnterprisesZip
(
eIds
:
string
[])
{
try
{
if
(
!
eIds
||
!
Array
.
isArray
(
eIds
))
{
throw
new
BizError
(
ERRORENUM
.
参数错误
,
'企业ID列表不能为空'
);
}
if
(
eIds
.
length
>
10
)
{
throw
new
BizError
(
ERRORENUM
.
参数错误
,
'一次最多只能下载10家企业'
);
}
const
projectRoot
=
path
.
resolve
(
__dirname
,
'../..'
);
const
tempBaseDir
=
path
.
join
(
projectRoot
,
'temp'
);
await
fs
.
ensureDir
(
tempBaseDir
);
// 创建总临时目录
const
tempDir
=
path
.
join
(
tempBaseDir
,
`temp_selected_enterprises_
${
Date
.
now
()}
`
);
console
.
log
(
`创建总临时目录:
${
tempDir
}
`
);
await
fs
.
ensureDir
(
tempDir
);
// 步骤1: 获取选中企业的详细信息
console
.
log
(
'=== 开始获取选中企业列表 ==='
);
const
enterprises
=
await
getSelectedEnterprises
(
eIds
);
console
.
log
(
`获取到
${
enterprises
.
length
}
家选中企业`
);
if
(
enterprises
.
length
===
0
)
{
throw
new
BizError
(
ERRORENUM
.
数据不存在
,
'未找到任何选中的企业数据'
);
}
// 步骤2: 为每家企业直接创建文件夹和文件(不生成单独的zip)
console
.
log
(
'=== 开始为选中企业创建文件夹和文件 ==='
);
const
enterpriseResults
=
await
generateEnterpriseFolders
(
enterprises
,
tempDir
);
// 步骤3: 创建包含所有企业文件夹的总zip文件
console
.
log
(
'=== 创建总zip文件 ==='
);
const
totalZipFileName
=
`选中企业完整数据_
${
moment
().
format
(
'YYYYMMDDHHmmss'
)}
.zip`
;
const
totalZipFilePath
=
path
.
join
(
tempBaseDir
,
totalZipFileName
);
console
.
log
(
`创建总ZIP文件:
${
totalZipFilePath
}
`
);
await
createZipArchive
(
tempDir
,
totalZipFilePath
);
const
zipStats
=
await
fs
.
stat
(
totalZipFilePath
);
console
.
log
(
`总ZIP文件创建成功,大小:
${
zipStats
.
size
}
bytes`
);
// 步骤4: 清理临时目录
console
.
log
(
'清理临时目录...'
);
await
fs
.
remove
(
tempDir
);
// 统计信息
const
successfulCount
=
enterpriseResults
.
filter
(
result
=>
result
.
success
).
length
;
const
failedCount
=
enterpriseResults
.
filter
(
result
=>
!
result
.
success
).
length
;
return
{
success
:
true
,
filePath
:
totalZipFilePath
,
fileName
:
totalZipFileName
,
statistics
:
{
total
:
enterprises
.
length
,
successful
:
successfulCount
,
failed
:
failedCount
,
details
:
enterpriseResults
}
};
}
catch
(
error
)
{
console
.
error
(
'下载选中企业zip包失败:'
,
error
);
throw
new
BizError
(
ERRORENUM
.
系统错误
,
'批量打包失败: '
+
error
.
message
);
}
}
/**
* 为每家企业直接创建文件夹和文件(不生成单独的zip)
*/
async
function
generateEnterpriseFolders
(
enterprises
:
any
[],
baseTempDir
:
string
):
Promise
<
any
[]
>
{
const
results
=
[];
// 限制并发数,避免内存溢出
const
BATCH_SIZE
=
3
;
// 每次同时处理3家企业
for
(
let
i
=
0
;
i
<
enterprises
.
length
;
i
+=
BATCH_SIZE
)
{
const
batch
=
enterprises
.
slice
(
i
,
i
+
BATCH_SIZE
);
console
.
log
(
`处理批次
${
Math
.
floor
(
i
/
BATCH_SIZE
)
+
1
}
: 企业
${
i
+
1
}
到
${
i
+
batch
.
length
}
`
);
const
batchPromises
=
batch
.
map
(
async
(
enterprise
)
=>
{
try
{
const
eId
=
enterprise
.
eId
;
const
enterpriseName
=
enterprise
.
enterpriseName
||
'未知企业'
;
console
.
log
(
`\n=== 开始处理企业:
${
enterpriseName
}
(
${
eId
}
) ===`
);
// 为每家企业创建文件夹(直接放在总目录下)
const
safeEnterpriseName
=
sanitizeFileName
(
enterpriseName
);
const
enterpriseFolderName
=
`
${
safeEnterpriseName
}
_
${
eId
}
`
;
const
enterpriseFolderPath
=
path
.
join
(
baseTempDir
,
enterpriseFolderName
);
await
fs
.
ensureDir
(
enterpriseFolderPath
);
console
.
log
(
`创建企业文件夹:
${
enterpriseFolderPath
}
`
);
// 生成企业详情Excel
await
generateEnterpriseDetailExcel
(
eId
,
enterpriseName
,
enterpriseFolderPath
);
// 下载企业相关文件到企业文件夹
await
downloadEnterpriseFiles
(
eId
,
enterpriseFolderPath
);
// 获取文件夹大小
const
folderSize
=
await
getFolderSize
(
enterpriseFolderPath
);
console
.
log
(
`✅ 企业
${
enterpriseName
}
处理完成,文件夹大小:
${
folderSize
}
bytes`
);
return
{
eId
,
enterpriseName
,
success
:
true
,
folderName
:
enterpriseFolderName
,
fileSize
:
folderSize
,
error
:
null
};
}
catch
(
error
)
{
console
.
error
(
`❌ 企业
${
enterprise
.
enterpriseName
}
(
${
enterprise
.
eId
}
) 处理失败:`
,
error
);
return
{
eId
:
enterprise
.
eId
,
enterpriseName
:
enterprise
.
enterpriseName
,
success
:
false
,
folderName
:
null
,
fileSize
:
0
,
error
:
error
.
message
};
}
});
const
batchResults
=
await
Promise
.
allSettled
(
batchPromises
);
// 处理批次结果
for
(
const
result
of
batchResults
)
{
if
(
result
.
status
===
'fulfilled'
)
{
results
.
push
(
result
.
value
);
}
else
{
console
.
error
(
'批次处理中出现未捕获的错误:'
,
result
.
reason
);
results
.
push
({
eId
:
'unknown'
,
enterpriseName
:
'未知企业'
,
success
:
false
,
folderName
:
null
,
fileSize
:
0
,
error
:
result
.
reason
.
message
});
}
}
// 批次间延迟,避免服务器压力过大
if
(
i
+
BATCH_SIZE
<
enterprises
.
length
)
{
console
.
log
(
'批次处理完成,等待2秒继续下一批...'
);
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
2000
));
}
}
return
results
;
}
/**
* 计算文件夹大小
*/
async
function
getFolderSize
(
folderPath
:
string
):
Promise
<
number
>
{
try
{
let
totalSize
=
0
;
const
items
=
await
fs
.
readdir
(
folderPath
);
for
(
const
item
of
items
)
{
const
itemPath
=
path
.
join
(
folderPath
,
item
);
const
stats
=
await
fs
.
stat
(
itemPath
);
if
(
stats
.
isDirectory
())
{
totalSize
+=
await
getFolderSize
(
itemPath
);
}
else
{
totalSize
+=
stats
.
size
;
}
}
return
totalSize
;
}
catch
(
error
)
{
console
.
error
(
`计算文件夹大小失败:
${
folderPath
}
`
,
error
);
return
0
;
}
}
/**
* 修改下载企业文件方法,创建分类子文件夹
*/
async
function
downloadEnterpriseFiles
(
eId
:
string
,
enterpriseFolderPath
:
string
)
{
// 创建分类子文件夹
const
categories
=
{
'租赁信息'
:
getLeaseFiles
,
'商标'
:
getTrademarkFiles
,
'作品著作权'
:
getCopyrightFiles
,
'软件著作权'
:
getSoftwareCopyrightFiles
,
'专利'
:
getPatentFiles
};
console
.
log
(
'=== 开始下载企业文件到分类文件夹 ==='
);
for
(
const
[
categoryName
,
fileGetter
]
of
Object
.
entries
(
categories
))
{
try
{
const
categoryFolderPath
=
path
.
join
(
enterpriseFolderPath
,
categoryName
);
await
fs
.
ensureDir
(
categoryFolderPath
);
console
.
log
(
`下载
${
categoryName
}
文件...`
);
const
files
=
await
fileGetter
(
eId
);
// 先验证文件存在性
const
validFiles
:
{
url
:
string
,
fileName
:
string
}[]
=
[];
for
(
const
file
of
files
)
{
const
exists
=
await
checkFileExists
(
file
.
url
);
if
(
exists
)
{
validFiles
.
push
(
file
);
console
.
log
(
`✅ 文件可用:
${
file
.
fileName
}
`
);
}
else
{
console
.
warn
(
`❌ 文件不存在,跳过:
${
file
.
fileName
}
`
);
}
}
console
.
log
(
`
${
categoryName
}
有效文件数量:
${
validFiles
.
length
}
/
${
files
.
length
}
`
);
// 只下载存在的文件
if
(
validFiles
.
length
>
0
)
{
await
downloadFilesToFolder
(
validFiles
,
categoryFolderPath
);
}
}
catch
(
error
)
{
console
.
error
(
`下载
${
categoryName
}
文件失败:`
,
error
);
// 继续处理其他分类,不中断整个流程
}
}
}
/**
* 下载文件到指定文件夹
*/
async
function
downloadFilesToFolder
(
files
:
{
url
:
string
,
fileName
:
string
}[],
targetFolder
:
string
):
Promise
<
void
>
{
if
(
files
.
length
===
0
)
{
return
;
}
const
downloadPromises
=
files
.
map
(
async
(
file
)
=>
{
try
{
if
(
!
file
.
url
||
typeof
file
.
url
!==
'string'
)
{
console
.
warn
(
`文件URL无效:`
,
file
.
url
);
return
;
}
console
.
log
(
`开始下载文件:
${
file
.
fileName
}
from
${
file
.
url
}
`
);
const
fetchOptions
:
any
=
{
method
:
'GET'
,
timeout
:
30000
,
headers
:
{
'User-Agent'
:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
,
'Accept'
:
'*/*'
}
};
// 添加认证 token
const
SECRET_TOKEN
=
"Ngz86cuAKxblwXR9OiKSWbfkj7oZ8R0lMU8pTfpVYBDCkvtUb0ZwbaBvwWyfv2O9"
;
if
(
file
.
url
.
includes
(
'192.168.0.71'
)
||
file
.
url
.
includes
(
'fh.tninnopark.cn'
))
{
fetchOptions
.
headers
[
'token'
]
=
SECRET_TOKEN
;
}
const
response
=
await
fetch
(
file
.
url
,
fetchOptions
);
if
(
!
response
.
ok
)
{
console
.
warn
(
`下载文件失败:
${
file
.
url
}
, 状态码:
${
response
.
status
}
`
);
return
;
}
const
buffer
=
await
response
.
buffer
();
if
(
buffer
.
length
===
0
)
{
console
.
warn
(
`文件内容为空:
${
file
.
fileName
}
`
);
return
;
}
const
filePath
=
path
.
join
(
targetFolder
,
file
.
fileName
);
await
fs
.
writeFile
(
filePath
,
buffer
);
console
.
log
(
`✅ 文件下载成功:
${
file
.
fileName
}
, 大小:
${
buffer
.
length
}
bytes`
);
}
catch
(
error
)
{
console
.
error
(
`下载文件失败:
${
file
.
fileName
}
(
${
file
.
url
}
)`
,
error
.
message
);
}
});
const
results
=
await
Promise
.
allSettled
(
downloadPromises
);
const
successful
=
results
.
filter
(
result
=>
result
.
status
===
'fulfilled'
).
length
;
const
failed
=
results
.
filter
(
result
=>
result
.
status
===
'rejected'
).
length
;
console
.
log
(
`文件夹
${
targetFolder
}
下载完成: 成功
${
successful
}
个, 失败
${
failed
}
个`
);
}
/**
* 获取选中企业的详细信息
*/
async
function
getSelectedEnterprises
(
eIds
:
string
[]):
Promise
<
any
[]
>
{
try
{
if
(
!
eIds
||
eIds
.
length
===
0
)
{
return
[];
}
let
selectParam
:
any
=
{
// state: enumConfig.CHANGESTATE.已通过,
eId
:
{
"%in%"
:
eIds
}
// 只查询选中的企业
};
// 主表字段
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"logonAddress"
,
"qiYeGuiMo"
];
let
manyTableInfo
:
any
=
{};
// let rufuSelectParam = { state: { "%between%": [enumConfig.FUHUASTATE.实体孵化, enumConfig.FUHUASTATE.虚拟孵化] } };
manyTableInfo
[
TABLENAME
.
企业孵化信息
]
=
{
column
:
[
"moveOutTime"
,
"moveOutType"
,
"startTime"
,
"endTime"
],
where
:
{}
};
// 执行多表联查
let
resInfo
=
await
selectManyTableData
(
OPERATIONALDATATYPE
.
多表联查
,
TABLENAME
.
企业基础信息表
,
selectParam
,
filesList
,
manyTableInfo
);
/**查询租赁表信息 */
let
leaseWhere
:
any
=
{
eId
:
{
"%in%"
:
eIds
}
};
let
zuLingList
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
TABLENAME
.
租赁信息
,
leaseWhere
,
[
"eId"
,
"area"
,
"startTime"
,
"endTime"
,
"building"
,
"roomNumber"
]);
let
zaifuMap
=
{};
if
(
zuLingList
.
length
)
{
zuLingList
.
forEach
(
info
=>
{
zaifuMap
[
info
.
eId
]
=
info
;
});
}
let
selectedEnterprises
=
[];
for
(
let
info
of
resInfo
)
{
let
{
eId
,
enterpriseName
,
uscc
,
logonTime
,
logonAddress
,
qiYeGuiMo
,
enterprise_fuhuas
,
}
=
info
;
let
leasesTime
=
'-'
;
if
(
zaifuMap
[
eId
]?.
startTime
)
{
leasesTime
=
`
${
moment
(
zaifuMap
[
eId
].
startTime
).
format
(
"YYYY-MM-DD"
)}
至
${
moment
(
zaifuMap
[
eId
].
endTime
).
format
(
"YYYY-MM-DD"
)}
`
;
}
let
fuhuaTime
=
'-'
;
if
(
enterprise_fuhuas
[
0
]?.
startTime
)
{
fuhuaTime
=
`
${
moment
(
enterprise_fuhuas
[
0
].
startTime
).
format
(
"YYYY-MM-DD"
)}
至
${
moment
(
enterprise_fuhuas
[
0
].
endTime
).
format
(
"YYYY-MM-DD"
)}
`
;
}
selectedEnterprises
.
push
({
eId
,
enterpriseName
,
uscc
,
logonTime
:
moment
(
logonTime
).
format
(
"YYYY-MM-DD"
),
logonAddress
:
changeAdd
(
JSON
.
parse
(
logonAddress
)),
qiYeGuiMo
,
fuhuaTime
,
leasesTime
,
area
:
zaifuMap
[
eId
]?.
area
?
`
${
zaifuMap
[
eId
].
area
}
㎡`
:
'-'
,
building
:
zaifuMap
[
eId
]?.
building
||
'-'
,
roomNumber
:
zaifuMap
[
eId
]?.
roomNumber
||
'-'
});
}
console
.
log
(
`获取到
${
selectedEnterprises
.
length
}
家选中企业`
);
return
selectedEnterprises
;
}
catch
(
error
)
{
console
.
error
(
'获取选中企业列表失败:'
,
error
);
throw
new
BizError
(
ERRORENUM
.
系统错误
,
'获取选中企业列表失败: '
+
error
.
message
);
}
}
/**
* 获取所有企业列表(支持过滤条件)
*/
async
function
getAllEnterprisesWithFilters
(
filters
:
{
enterpriseName
?:
string
;
logonStartTime
?:
Number
;
logonEndTime
?:
Number
;
startTime
?:
Number
;
endTime
?:
Number
;
building
?:
number
;
}
=
{}):
Promise
<
any
[]
>
{
try
{
let
selectParam
:
any
=
{
state
:
enumConfig
.
CHANGESTATE
.
已通过
};
// 应用过滤条件
if
(
filters
.
enterpriseName
)
{
selectParam
.
enterpriseName
=
{
"%like%"
:
filters
.
enterpriseName
};
}
if
(
filters
.
logonStartTime
&&
filters
.
logonEndTime
)
{
selectParam
.
logonTime
=
{
"%between%"
:
[
getMySqlMs
(
filters
.
logonStartTime
),
getMySqlMs
(
filters
.
logonEndTime
)]
};
}
// 主表字段
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"logonAddress"
,
"qiYeGuiMo"
];
let
manyTableInfo
:
any
=
{};
let
rufuSelectParam
=
{
state
:
{
"%between%"
:
[
enumConfig
.
FUHUASTATE
.
实体孵化
,
enumConfig
.
FUHUASTATE
.
虚拟孵化
]
}
};
manyTableInfo
[
TABLENAME
.
企业孵化信息
]
=
{
column
:
[
"moveOutTime"
,
"moveOutType"
,
"startTime"
,
"endTime"
],
where
:
rufuSelectParam
};
// 执行多表联查
let
resInfo
=
await
selectManyTableData
(
OPERATIONALDATATYPE
.
多表联查
,
TABLENAME
.
企业基础信息表
,
selectParam
,
filesList
,
manyTableInfo
);
/**查询租赁表信息 */
let
leaseWhere
:
any
=
{};
if
(
filters
.
building
)
{
leaseWhere
.
building
=
filters
.
building
;
}
// 时间范围过滤(如果需要的话)
// if (filters.startTime && filters.endTime) {
// leaseWhere["%literal%"] = `(startTime BETWEEN '${getMySqlMs(filters.startTime)}' and '${getMySqlMs(filters.endTime)}' or endTime BETWEEN '${getMySqlMs(filters.startTime)}' and '${getMySqlMs(filters.endTime)}') `;
// }
let
zuLingList
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
TABLENAME
.
租赁信息
,
leaseWhere
,
[
"eId"
,
"area"
,
"startTime"
,
"endTime"
,
"building"
,
"roomNumber"
]);
let
zaifuMap
=
{};
if
(
zuLingList
.
length
)
{
zuLingList
.
forEach
(
info
=>
{
zaifuMap
[
info
.
eId
]
=
info
;
});
}
let
allEnterprises
=
[];
for
(
let
info
of
resInfo
)
{
let
{
eId
,
enterpriseName
,
uscc
,
logonTime
,
logonAddress
,
qiYeGuiMo
,
enterprise_fuhuas
,
}
=
info
;
// 如果有租赁信息过滤条件,只包含有匹配租赁记录的企业
if
(
Object
.
keys
(
leaseWhere
).
length
&&
!
zaifuMap
[
eId
])
{
continue
;
}
let
leasesTime
=
'-'
;
if
(
zaifuMap
[
eId
]?.
startTime
)
{
leasesTime
=
`
${
moment
(
zaifuMap
[
eId
].
startTime
).
format
(
"YYYY-MM-DD"
)}
至
${
moment
(
zaifuMap
[
eId
].
endTime
).
format
(
"YYYY-MM-DD"
)}
`
;
}
let
fuhuaTime
=
'-'
;
if
(
enterprise_fuhuas
[
0
]?.
startTime
)
{
fuhuaTime
=
`
${
moment
(
enterprise_fuhuas
[
0
].
startTime
).
format
(
"YYYY-MM-DD"
)}
至
${
moment
(
enterprise_fuhuas
[
0
].
endTime
).
format
(
"YYYY-MM-DD"
)}
`
;
}
allEnterprises
.
push
({
eId
,
enterpriseName
,
uscc
,
logonTime
:
moment
(
logonTime
).
format
(
"YYYY-MM-DD"
),
logonAddress
:
changeAdd
(
JSON
.
parse
(
logonAddress
)),
qiYeGuiMo
,
fuhuaTime
,
leasesTime
,
area
:
zaifuMap
[
eId
]?.
area
?
`
${
zaifuMap
[
eId
].
area
}
㎡`
:
'-'
,
building
:
zaifuMap
[
eId
]?.
building
||
'-'
,
roomNumber
:
zaifuMap
[
eId
]?.
roomNumber
||
'-'
});
}
console
.
log
(
`获取到
${
allEnterprises
.
length
}
家符合条件的企业`
);
return
allEnterprises
;
}
catch
(
error
)
{
console
.
error
(
'获取企业列表失败:'
,
error
);
throw
new
BizError
(
ERRORENUM
.
系统错误
,
'获取企业列表失败: '
+
error
.
message
);
}
}
/**
* 为每家企业生成单独的zip包
*/
async
function
generateEnterpriseZips
(
enterprises
:
any
[],
baseTempDir
:
string
):
Promise
<
any
[]
>
{
const
results
=
[];
// 限制并发数,避免内存溢出
const
BATCH_SIZE
=
3
;
// 每次同时处理3家企业
for
(
let
i
=
0
;
i
<
enterprises
.
length
;
i
+=
BATCH_SIZE
)
{
const
batch
=
enterprises
.
slice
(
i
,
i
+
BATCH_SIZE
);
console
.
log
(
`处理批次
${
Math
.
floor
(
i
/
BATCH_SIZE
)
+
1
}
: 企业
${
i
+
1
}
到
${
i
+
batch
.
length
}
`
);
const
batchPromises
=
batch
.
map
(
async
(
enterprise
)
=>
{
try
{
const
eId
=
enterprise
.
eId
;
const
enterpriseName
=
enterprise
.
enterpriseName
||
'未知企业'
;
console
.
log
(
`\n=== 开始处理第
${
i
+
1
}
家企业:
${
enterpriseName
}
(
${
eId
}
) ===`
);
// 为每家企业创建单独目录
const
enterpriseTempDir
=
path
.
join
(
baseTempDir
,
`enterprise_
${
eId
}
`
);
await
fs
.
ensureDir
(
enterpriseTempDir
);
// 生成企业详情Excel
const
excelFilePath
=
await
generateEnterpriseDetailExcel
(
eId
,
enterpriseName
,
enterpriseTempDir
);
// 下载企业相关文件
await
downloadEnterpriseFiles
(
eId
,
enterpriseTempDir
);
// 创建企业单独的zip包
const
safeEnterpriseName
=
sanitizeFileName
(
enterpriseName
);
const
enterpriseZipFileName
=
`企业完整数据_
${
safeEnterpriseName
}
_
${
eId
}
.zip`
;
// 修复:直接创建到总目录,避免移动操作
const
enterpriseZipFilePath
=
path
.
join
(
baseTempDir
,
enterpriseZipFileName
);
console
.
log
(
`创建企业ZIP文件:
${
enterpriseZipFilePath
}
`
);
await
createZipArchive
(
enterpriseTempDir
,
enterpriseZipFilePath
);
// 清理企业临时目录
await
fs
.
remove
(
enterpriseTempDir
);
const
zipStats
=
await
fs
.
stat
(
enterpriseZipFilePath
);
console
.
log
(
`✅ 企业
${
enterpriseName
}
处理完成,文件大小:
${
zipStats
.
size
}
bytes`
);
return
{
eId
,
enterpriseName
,
success
:
true
,
fileName
:
enterpriseZipFileName
,
fileSize
:
zipStats
.
size
,
error
:
null
};
}
catch
(
error
)
{
console
.
error
(
`❌ 企业
${
enterprise
.
enterpriseName
}
(
${
enterprise
.
eId
}
) 处理失败:`
,
error
);
return
{
eId
:
enterprise
.
eId
,
enterpriseName
:
enterprise
.
enterpriseName
,
success
:
false
,
fileName
:
null
,
fileSize
:
0
,
error
:
error
.
message
};
}
});
const
batchResults
=
await
Promise
.
allSettled
(
batchPromises
);
// 处理批次结果
for
(
const
result
of
batchResults
)
{
if
(
result
.
status
===
'fulfilled'
)
{
results
.
push
(
result
.
value
);
}
else
{
console
.
error
(
'批次处理中出现未捕获的错误:'
,
result
.
reason
);
results
.
push
({
eId
:
'unknown'
,
enterpriseName
:
'未知企业'
,
success
:
false
,
fileName
:
null
,
fileSize
:
0
,
error
:
result
.
reason
.
message
});
}
}
// 批次间延迟,避免服务器压力过大
if
(
i
+
BATCH_SIZE
<
enterprises
.
length
)
{
console
.
log
(
'批次处理完成,等待2秒继续下一批...'
);
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
2000
));
}
}
return
results
;
}
/**
* 改进的下载企业文件方法,增加超时和重试机制
*/
async
function
downloadEnterpriseFilesWithRetry
(
eId
:
string
,
tempDir
:
string
,
maxRetries
:
number
=
2
):
Promise
<
void
>
{
for
(
let
attempt
=
1
;
attempt
<=
maxRetries
+
1
;
attempt
++
)
{
try
{
await
downloadEnterpriseFiles
(
eId
,
tempDir
);
return
;
// 成功则返回
}
catch
(
error
)
{
console
.
warn
(
`下载企业文件尝试
${
attempt
}
失败:`
,
error
.
message
);
if
(
attempt
<=
maxRetries
)
{
console
.
log
(
`等待
${
attempt
*
2
}
秒后重试...`
);
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
attempt
*
2000
));
}
else
{
throw
error
;
// 所有重试都失败,抛出错误
}
}
}
}
/**
* 获取所有企业列表(去除分页效果)
*/
async
function
getAllEnterprises
():
Promise
<
any
[]
>
{
try
{
// 使用与 enterpriseList 相同的查询逻辑,但不进行分页
let
selectParam
:
any
=
{
state
:
enumConfig
.
CHANGESTATE
.
已通过
};
// 主表字段过滤参数保持不变
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"logonAddress"
,
"qiYeGuiMo"
];
let
manyTableInfo
:
any
=
{};
let
rufuSelectParam
=
{
state
:
{
"%between%"
:
[
enumConfig
.
FUHUASTATE
.
实体孵化
,
enumConfig
.
FUHUASTATE
.
虚拟孵化
]
}
};
manyTableInfo
[
TABLENAME
.
企业孵化信息
]
=
{
column
:
[
"moveOutTime"
,
"moveOutType"
,
"startTime"
,
"endTime"
],
where
:
rufuSelectParam
};
// 执行多表联查,不添加分页参数
let
resInfo
=
await
selectManyTableData
(
OPERATIONALDATATYPE
.
多表联查
,
TABLENAME
.
企业基础信息表
,
selectParam
,
filesList
,
manyTableInfo
);
/**查询租赁表信息 */
let
zuLingList
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
TABLENAME
.
租赁信息
,
{},
[
"eId"
,
"area"
,
"startTime"
,
"endTime"
,
"building"
,
"roomNumber"
]);
let
zaifuMap
=
{};
if
(
zuLingList
.
length
)
{
zuLingList
.
forEach
(
info
=>
{
zaifuMap
[
info
.
eId
]
=
info
;
});
}
let
allEnterprises
=
[];
for
(
let
info
of
resInfo
)
{
let
{
eId
,
enterpriseName
,
uscc
,
logonTime
,
logonAddress
,
qiYeGuiMo
,
enterprise_fuhuas
,
}
=
info
;
// 如果有租赁信息,只包含有租赁记录的企业
if
(
Object
.
keys
(
zaifuMap
).
length
&&
!
zaifuMap
[
eId
])
{
continue
;
}
let
leasesTime
=
'-'
;
if
(
zaifuMap
[
eId
]?.
startTime
)
{
leasesTime
=
`
${
moment
(
zaifuMap
[
eId
].
startTime
).
format
(
"YYYY-MM-DD"
)}
至
${
moment
(
zaifuMap
[
eId
].
endTime
).
format
(
"YYYY-MM-DD"
)}
`
;
}
let
fuhuaTime
=
'-'
;
if
(
enterprise_fuhuas
[
0
]?.
startTime
)
{
fuhuaTime
=
`
${
moment
(
enterprise_fuhuas
[
0
].
startTime
).
format
(
"YYYY-MM-DD"
)}
至
${
moment
(
enterprise_fuhuas
[
0
].
endTime
).
format
(
"YYYY-MM-DD"
)}
`
;
}
allEnterprises
.
push
({
eId
,
enterpriseName
,
// 企业名称
uscc
,
// 统一信用代码
logonTime
:
moment
(
logonTime
).
format
(
"YYYY-MM-DD"
),
// 注册日期
logonAddress
:
changeAdd
(
JSON
.
parse
(
logonAddress
)),
// 注册地址
qiYeGuiMo
,
// 企业规模
fuhuaTime
,
// 孵化时间
leasesTime
,
// 租赁时间
area
:
zaifuMap
[
eId
]?.
area
?
`
${
zaifuMap
[
eId
].
area
}
㎡`
:
'-'
,
building
:
zaifuMap
[
eId
]?.
building
||
'-'
,
roomNumber
:
zaifuMap
[
eId
]?.
roomNumber
||
'-'
});
}
console
.
log
(
`获取到
${
allEnterprises
.
length
}
家在孵企业`
);
return
allEnterprises
;
}
catch
(
error
)
{
console
.
error
(
'获取企业列表失败:'
,
error
);
throw
new
BizError
(
ERRORENUM
.
系统错误
,
'获取企业列表失败: '
+
error
.
message
);
}
}
/**
* 下载所有企业的zip包文件
*/
export
async
function
downloadAllEnterprisesZip
()
{
try
{
const
projectRoot
=
path
.
resolve
(
__dirname
,
'../..'
);
const
tempBaseDir
=
path
.
join
(
projectRoot
,
'temp'
);
await
fs
.
ensureDir
(
tempBaseDir
);
// 创建总临时目录
const
tempDir
=
path
.
join
(
tempBaseDir
,
`temp_all_enterprises_
${
Date
.
now
()}
`
);
console
.
log
(
`创建总临时目录:
${
tempDir
}
`
);
await
fs
.
ensureDir
(
tempDir
);
// 步骤1: 获取所有企业列表
console
.
log
(
'=== 开始获取所有企业列表 ==='
);
const
enterprises
=
await
getAllEnterprises
();
console
.
log
(
`获取到
${
enterprises
.
length
}
家企业`
);
if
(
enterprises
.
length
===
0
)
{
throw
new
BizError
(
ERRORENUM
.
数据不存在
,
'未找到任何企业数据'
);
}
// 步骤2: 为每家企业生成单独的zip包
console
.
log
(
'=== 开始为每家企业生成zip包 ==='
);
const
enterpriseZipResults
=
await
generateEnterpriseZips
(
enterprises
,
tempDir
);
// 步骤3: 创建包含所有企业zip包的总zip文件
console
.
log
(
'=== 创建总zip文件 ==='
);
const
totalZipFileName
=
`所有企业完整数据_
${
moment
().
format
(
'YYYYMMDDHHmmss'
)}
.zip`
;
const
totalZipFilePath
=
path
.
join
(
tempBaseDir
,
totalZipFileName
);
console
.
log
(
`创建总ZIP文件:
${
totalZipFilePath
}
`
);
await
createZipArchive
(
tempDir
,
totalZipFilePath
);
const
zipStats
=
await
fs
.
stat
(
totalZipFilePath
);
console
.
log
(
`总ZIP文件创建成功,大小:
${
zipStats
.
size
}
bytes`
);
// 步骤4: 清理临时目录
console
.
log
(
'清理临时目录...'
);
await
fs
.
remove
(
tempDir
);
// 统计信息
const
successfulCount
=
enterpriseZipResults
.
filter
(
result
=>
result
.
success
).
length
;
const
failedCount
=
enterpriseZipResults
.
filter
(
result
=>
!
result
.
success
).
length
;
return
{
success
:
true
,
filePath
:
totalZipFilePath
,
fileName
:
totalZipFileName
,
statistics
:
{
total
:
enterprises
.
length
,
successful
:
successfulCount
,
failed
:
failedCount
,
details
:
enterpriseZipResults
}
};
}
catch
(
error
)
{
console
.
error
(
'下载所有企业zip包失败:'
,
error
);
throw
new
BizError
(
ERRORENUM
.
系统错误
,
'批量打包失败: '
+
error
.
message
);
}
}
/**
* 增强的下载所有企业zip包方法(支持过滤条件)
*/
export
async
function
downloadAllEnterprisesZipWithFilters
(
filters
?:
{
enterpriseName
?:
string
;
logonStartTime
?:
Number
;
logonEndTime
?:
Number
;
startTime
?:
Number
;
endTime
?:
Number
;
building
?:
number
;
})
{
try
{
const
projectRoot
=
path
.
resolve
(
__dirname
,
'../..'
);
const
tempBaseDir
=
path
.
join
(
projectRoot
,
'temp'
);
await
fs
.
ensureDir
(
tempBaseDir
);
// 创建总临时目录
const
tempDir
=
path
.
join
(
tempBaseDir
,
`temp_all_enterprises_
${
Date
.
now
()}
`
);
console
.
log
(
`创建总临时目录:
${
tempDir
}
`
);
await
fs
.
ensureDir
(
tempDir
);
// 步骤1: 获取所有企业列表(带过滤条件)
console
.
log
(
'=== 开始获取所有企业列表 ==='
);
const
enterprises
=
await
getAllEnterprisesWithFilters
(
filters
);
console
.
log
(
`获取到
${
enterprises
.
length
}
家企业`
);
if
(
enterprises
.
length
===
0
)
{
throw
new
BizError
(
ERRORENUM
.
数据不存在
,
'未找到任何符合条件的企业数据'
);
}
// 步骤2: 为每家企业生成单独的zip包
console
.
log
(
'=== 开始为每家企业生成zip包 ==='
);
const
enterpriseZipResults
=
await
generateEnterpriseZips
(
enterprises
,
tempDir
);
// 步骤3: 创建包含所有企业zip包的总zip文件
console
.
log
(
'=== 创建总zip文件 ==='
);
const
filterSuffix
=
filters
?
'_筛选结果'
:
''
;
const
totalZipFileName
=
`所有企业完整数据
${
filterSuffix
}
_
${
moment
().
format
(
'YYYYMMDDHHmmss'
)}
.zip`
;
const
totalZipFilePath
=
path
.
join
(
tempBaseDir
,
totalZipFileName
);
console
.
log
(
`创建总ZIP文件:
${
totalZipFilePath
}
`
);
await
createZipArchive
(
tempDir
,
totalZipFilePath
);
const
zipStats
=
await
fs
.
stat
(
totalZipFilePath
);
console
.
log
(
`总ZIP文件创建成功,大小:
${
zipStats
.
size
}
bytes`
);
// 步骤4: 清理临时目录
console
.
log
(
'清理临时目录...'
);
await
fs
.
remove
(
tempDir
);
// 统计信息
const
successfulCount
=
enterpriseZipResults
.
filter
(
result
=>
result
.
success
).
length
;
const
failedCount
=
enterpriseZipResults
.
filter
(
result
=>
!
result
.
success
).
length
;
return
{
success
:
true
,
filePath
:
totalZipFilePath
,
fileName
:
totalZipFileName
,
statistics
:
{
total
:
enterprises
.
length
,
successful
:
successfulCount
,
failed
:
failedCount
,
filters
:
filters
||
{},
details
:
enterpriseZipResults
}
};
}
catch
(
error
)
{
console
.
error
(
'下载所有企业zip包失败:'
,
error
);
throw
new
BizError
(
ERRORENUM
.
系统错误
,
'批量打包失败: '
+
error
.
message
);
}
}
/**
* 下载企业相关文件、数据表格和详情Excel的zip包
*/
export
async
function
downloadEnterpriseFilesZip
(
eId
:
string
)
{
if
(
!
eId
)
throw
new
BizError
(
ERRORENUM
.
参数错误
,
`下载企业文件缺失eId`
);
try
{
const
projectRoot
=
path
.
resolve
(
__dirname
,
'../..'
);
const
tempBaseDir
=
path
.
join
(
projectRoot
,
'temp'
);
await
fs
.
ensureDir
(
tempBaseDir
);
const
tempDir
=
path
.
join
(
tempBaseDir
,
`temp_enterprise_files_
${
eId
}
_
${
Date
.
now
()}
`
);
console
.
log
(
`创建临时目录:
${
tempDir
}
`
);
await
fs
.
ensureDir
(
tempDir
);
// 获取企业名称
console
.
log
(
'=== 开始获取企业信息 ==='
);
const
enterpriseInfo
=
await
getEnterpriseInfo
(
eId
);
const
enterpriseName
=
enterpriseInfo
?.
enterpriseName
||
'未知企业'
;
console
.
log
(
`企业名称:
${
enterpriseName
}
`
);
// 步骤1: 获取企业详情数据并生成Excel
console
.
log
(
'=== 开始生成企业详情Excel ==='
);
const
excelFilePath
=
await
generateEnterpriseDetailExcel
(
eId
,
enterpriseName
,
tempDir
);
// 步骤2: 下载企业相关文件
console
.
log
(
'=== 开始下载企业文件 ==='
);
await
downloadEnterpriseFiles
(
eId
,
tempDir
);
// 步骤3: 创建zip文件
const
safeEnterpriseName
=
sanitizeFileName
(
enterpriseName
);
const
zipFileName
=
`企业完整数据_
${
safeEnterpriseName
}
_
${
eId
}
_
${
moment
().
format
(
'YYYYMMDDHHmmss'
)}
.zip`
;
const
zipFilePath
=
path
.
join
(
tempBaseDir
,
zipFileName
);
console
.
log
(
`创建ZIP文件:
${
zipFilePath
}
`
);
await
createZipArchive
(
tempDir
,
zipFilePath
);
const
zipStats
=
await
fs
.
stat
(
zipFilePath
);
console
.
log
(
`ZIP文件创建成功,大小:
${
zipStats
.
size
}
bytes`
);
// 清理临时目录
console
.
log
(
'清理临时目录...'
);
await
fs
.
remove
(
tempDir
);
return
{
success
:
true
,
filePath
:
zipFilePath
,
fileName
:
zipFileName
};
}
catch
(
error
)
{
console
.
error
(
'下载企业文件zip包失败:'
,
error
);
throw
new
BizError
(
ERRORENUM
.
系统错误
,
'文件打包失败: '
+
error
.
message
);
}
}
/**
* 生成企业详情Excel文件
*/
async
function
generateEnterpriseDetailExcel
(
eId
:
string
,
enterpriseName
:
string
,
tempDir
:
string
):
Promise
<
string
>
{
try
{
console
.
log
(
'获取企业详情数据...'
);
const
details
=
await
getAllDwOutPut
(
eId
);
console
.
log
(
'企业详情数据结构:'
,
JSON
.
stringify
(
details
,
null
,
2
));
const
safeEnterpriseName
=
sanitizeFileName
(
enterpriseName
);
const
excelFileName
=
`企业详情_
${
safeEnterpriseName
}
_
${
eId
}
.xlsx`
;
const
excelFilePath
=
path
.
join
(
tempDir
,
excelFileName
);
const
workbook
=
new
ExcelJS
.
Workbook
();
// 设置文档属性
workbook
.
creator
=
'企业管理系统'
;
workbook
.
lastModifiedBy
=
'企业管理系统'
;
workbook
.
created
=
new
Date
();
workbook
.
modified
=
new
Date
();
// 1. 基础信息工作表
await
createBasicInfoSheet
(
workbook
,
details
.
enterprise
,
'基础信息'
);
// 2. 经营数据工作表
await
createBusinessDataSheet
(
workbook
,
details
.
manage
,
'经营数据'
);
// 3. 融资情况工作表
await
createFinancingSheet
(
workbook
,
details
.
financing
,
'融资情况'
);
// 4. 荣誉奖项工作表
await
createHonorSheet
(
workbook
,
details
.
honor
,
'荣誉奖项'
);
// 保存Excel文件
await
workbook
.
xlsx
.
writeFile
(
excelFilePath
);
console
.
log
(
`Excel文件生成成功:
${
excelFilePath
}
`
);
return
excelFilePath
;
}
catch
(
error
)
{
console
.
error
(
'生成企业详情Excel失败:'
,
error
);
throw
new
BizError
(
ERRORENUM
.
系统错误
,
'生成Excel文件失败: '
+
error
.
message
);
}
}
/**
* 创建基础信息工作表 - 表格格式
*/
async
function
createBasicInfoSheet
(
workbook
:
ExcelJS
.
Workbook
,
enterpriseData
:
any
,
sheetName
:
string
)
{
const
worksheet
=
workbook
.
addWorksheet
(
sheetName
);
if
(
!
enterpriseData
||
!
enterpriseData
.
dataList
||
!
Array
.
isArray
(
enterpriseData
.
dataList
))
{
worksheet
.
getCell
(
'A1'
).
value
=
'暂无基础信息数据'
;
return
;
}
const
dataList
=
enterpriseData
.
dataList
;
// 设置列宽
worksheet
.
columns
=
[
{
width
:
15
},
{
width
:
20
},
{
width
:
15
},
{
width
:
25
},
{
width
:
12
},
{
width
:
25
},
{
width
:
12
},
{
width
:
8
},
{
width
:
8
}
];
// 添加标题
worksheet
.
mergeCells
(
'A1:I1'
);
const
titleCell
=
worksheet
.
getCell
(
'A1'
);
titleCell
.
value
=
'企业基础信息'
;
titleCell
.
font
=
{
bold
:
true
,
size
:
14
};
titleCell
.
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
titleCell
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FFDDEBF7'
}
};
// 添加表头(第一行)
if
(
dataList
.
length
>
0
&&
Array
.
isArray
(
dataList
[
0
]))
{
const
headerRow
=
worksheet
.
addRow
(
dataList
[
0
]);
// 设置表头样式
headerRow
.
font
=
{
bold
:
true
,
color
:
{
argb
:
'FFFFFFFF'
}
};
headerRow
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FF2F75B5'
}
};
headerRow
.
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
headerRow
.
height
=
25
;
}
// 添加数据行(从第二行开始)
let
currentRow
=
3
;
// 标题占1行,表头占1行,数据从第3行开始
for
(
let
i
=
1
;
i
<
dataList
.
length
;
i
++
)
{
if
(
Array
.
isArray
(
dataList
[
i
]))
{
const
dataRow
=
worksheet
.
addRow
(
dataList
[
i
]);
// 设置数据行样式
dataRow
.
alignment
=
{
horizontal
:
'left'
,
vertical
:
'middle'
};
// 交替行颜色
if
(
i
%
2
===
0
)
{
dataRow
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FFF2F2F2'
}
};
}
currentRow
++
;
}
}
// 设置边框
const
dataRange
=
`A2:I
${
currentRow
}
`
;
for
(
let
row
=
2
;
row
<=
currentRow
;
row
++
)
{
for
(
let
col
=
1
;
col
<=
9
;
col
++
)
{
const
cell
=
worksheet
.
getCell
(
row
,
col
);
cell
.
border
=
{
top
:
{
style
:
'thin'
},
left
:
{
style
:
'thin'
},
bottom
:
{
style
:
'thin'
},
right
:
{
style
:
'thin'
}
};
}
}
console
.
log
(
`基础信息工作表创建完成,共
${
dataList
.
length
-
1
}
条数据`
);
}
/**
* 创建经营数据工作表
*/
async
function
createBusinessDataSheet
(
workbook
:
ExcelJS
.
Workbook
,
manageData
:
any
,
sheetName
:
string
)
{
const
worksheet
=
workbook
.
addWorksheet
(
sheetName
);
if
(
!
manageData
||
!
manageData
.
dataList
||
!
Array
.
isArray
(
manageData
.
dataList
))
{
worksheet
.
getCell
(
'A1'
).
value
=
'暂无经营数据'
;
return
;
}
const
dataList
=
manageData
.
dataList
;
// 设置列宽
worksheet
.
columns
=
[
{
width
:
15
},
{
width
:
20
},
{
width
:
15
},
{
width
:
15
},
{
width
:
15
},
{
width
:
15
}
];
// 添加标题
worksheet
.
mergeCells
(
'A1:F1'
);
const
titleCell
=
worksheet
.
getCell
(
'A1'
);
titleCell
.
value
=
'企业经营数据'
;
titleCell
.
font
=
{
bold
:
true
,
size
:
14
};
titleCell
.
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
titleCell
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FFE2EFDA'
}
};
// 添加表头(第一行)
if
(
dataList
.
length
>
0
&&
Array
.
isArray
(
dataList
[
0
]))
{
const
headerRow
=
worksheet
.
addRow
(
dataList
[
0
]);
// 设置表头样式
headerRow
.
font
=
{
bold
:
true
,
color
:
{
argb
:
'FFFFFFFF'
}
};
headerRow
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FF70AD47'
}
};
headerRow
.
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
headerRow
.
height
=
25
;
}
// 添加数据行
let
currentRow
=
3
;
let
hasData
=
false
;
for
(
let
i
=
1
;
i
<
dataList
.
length
;
i
++
)
{
if
(
Array
.
isArray
(
dataList
[
i
])
&&
dataList
[
i
].
some
((
cell
:
any
)
=>
cell
&&
cell
!==
'-'
))
{
const
dataRow
=
worksheet
.
addRow
(
dataList
[
i
]);
// 设置数据行样式
dataRow
.
alignment
=
{
horizontal
:
'left'
,
vertical
:
'middle'
};
// 交替行颜色
if
(
i
%
2
===
0
)
{
dataRow
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FFF2F2F2'
}
};
}
currentRow
++
;
hasData
=
true
;
}
}
if
(
!
hasData
)
{
worksheet
.
getCell
(
'A3'
).
value
=
'暂无经营数据'
;
worksheet
.
getCell
(
'A3'
).
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
}
else
{
// 设置边框
const
dataRange
=
`A2:F
${
currentRow
}
`
;
for
(
let
row
=
2
;
row
<=
currentRow
;
row
++
)
{
for
(
let
col
=
1
;
col
<=
6
;
col
++
)
{
const
cell
=
worksheet
.
getCell
(
row
,
col
);
cell
.
border
=
{
top
:
{
style
:
'thin'
},
left
:
{
style
:
'thin'
},
bottom
:
{
style
:
'thin'
},
right
:
{
style
:
'thin'
}
};
}
}
}
console
.
log
(
`经营数据工作表创建完成,共
${
dataList
.
length
-
1
}
条数据`
);
}
/**
* 创建融资情况工作表
*/
async
function
createFinancingSheet
(
workbook
:
ExcelJS
.
Workbook
,
financingData
:
any
,
sheetName
:
string
)
{
const
worksheet
=
workbook
.
addWorksheet
(
sheetName
);
if
(
!
financingData
||
!
financingData
.
dataList
||
!
Array
.
isArray
(
financingData
.
dataList
))
{
worksheet
.
getCell
(
'A1'
).
value
=
'暂无融资数据'
;
return
;
}
const
dataList
=
financingData
.
dataList
;
// 设置列宽
worksheet
.
columns
=
[
{
width
:
15
},
{
width
:
20
},
{
width
:
15
},
{
width
:
15
},
{
width
:
15
},
{
width
:
20
}
];
// 添加标题
worksheet
.
mergeCells
(
'A1:F1'
);
const
titleCell
=
worksheet
.
getCell
(
'A1'
);
titleCell
.
value
=
'企业融资情况'
;
titleCell
.
font
=
{
bold
:
true
,
size
:
14
};
titleCell
.
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
titleCell
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FFFFE699'
}
};
// 添加表头(第一行)
if
(
dataList
.
length
>
0
&&
Array
.
isArray
(
dataList
[
0
]))
{
const
headerRow
=
worksheet
.
addRow
(
dataList
[
0
]);
// 设置表头样式
headerRow
.
font
=
{
bold
:
true
,
color
:
{
argb
:
'FFFFFFFF'
}
};
headerRow
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FFFFC000'
}
};
headerRow
.
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
headerRow
.
height
=
25
;
}
// 添加数据行
let
currentRow
=
3
;
let
hasData
=
false
;
for
(
let
i
=
1
;
i
<
dataList
.
length
;
i
++
)
{
if
(
Array
.
isArray
(
dataList
[
i
])
&&
dataList
[
i
].
some
((
cell
:
any
)
=>
cell
&&
cell
!==
'-'
))
{
const
dataRow
=
worksheet
.
addRow
(
dataList
[
i
]);
// 设置数据行样式
dataRow
.
alignment
=
{
horizontal
:
'left'
,
vertical
:
'middle'
};
// 交替行颜色
if
(
i
%
2
===
0
)
{
dataRow
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FFF2F2F2'
}
};
}
currentRow
++
;
hasData
=
true
;
}
}
if
(
!
hasData
)
{
worksheet
.
getCell
(
'A3'
).
value
=
'暂无融资数据'
;
worksheet
.
getCell
(
'A3'
).
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
}
else
{
// 设置边框
for
(
let
row
=
2
;
row
<=
currentRow
;
row
++
)
{
for
(
let
col
=
1
;
col
<=
6
;
col
++
)
{
const
cell
=
worksheet
.
getCell
(
row
,
col
);
cell
.
border
=
{
top
:
{
style
:
'thin'
},
left
:
{
style
:
'thin'
},
bottom
:
{
style
:
'thin'
},
right
:
{
style
:
'thin'
}
};
}
}
}
console
.
log
(
`融资情况工作表创建完成,共
${
dataList
.
length
-
1
}
条数据`
);
}
/**
* 创建荣誉奖项工作表
*/
async
function
createHonorSheet
(
workbook
:
ExcelJS
.
Workbook
,
honorData
:
any
,
sheetName
:
string
)
{
const
worksheet
=
workbook
.
addWorksheet
(
sheetName
);
if
(
!
honorData
||
!
honorData
.
dataList
||
!
Array
.
isArray
(
honorData
.
dataList
))
{
worksheet
.
getCell
(
'A1'
).
value
=
'暂无荣誉数据'
;
return
;
}
const
dataList
=
honorData
.
dataList
;
// 设置列宽
worksheet
.
columns
=
[
{
width
:
15
},
{
width
:
25
},
{
width
:
20
},
{
width
:
15
},
{
width
:
15
}
];
// 添加标题
worksheet
.
mergeCells
(
'A1:E1'
);
const
titleCell
=
worksheet
.
getCell
(
'A1'
);
titleCell
.
value
=
'企业荣誉奖项'
;
titleCell
.
font
=
{
bold
:
true
,
size
:
14
};
titleCell
.
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
titleCell
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FFE6E0EC'
}
};
// 添加表头(第一行)
if
(
dataList
.
length
>
0
&&
Array
.
isArray
(
dataList
[
0
]))
{
const
headerRow
=
worksheet
.
addRow
(
dataList
[
0
]);
// 设置表头样式
headerRow
.
font
=
{
bold
:
true
,
color
:
{
argb
:
'FFFFFFFF'
}
};
headerRow
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FF8064A2'
}
};
headerRow
.
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
headerRow
.
height
=
25
;
}
// 添加数据行
let
currentRow
=
3
;
let
hasData
=
false
;
for
(
let
i
=
1
;
i
<
dataList
.
length
;
i
++
)
{
if
(
Array
.
isArray
(
dataList
[
i
])
&&
dataList
[
i
].
some
((
cell
:
any
)
=>
cell
&&
cell
!==
'-'
))
{
const
dataRow
=
worksheet
.
addRow
(
dataList
[
i
]);
// 设置数据行样式
dataRow
.
alignment
=
{
horizontal
:
'left'
,
vertical
:
'middle'
};
// 交替行颜色
if
(
i
%
2
===
0
)
{
dataRow
.
fill
=
{
type
:
'pattern'
,
pattern
:
'solid'
,
fgColor
:
{
argb
:
'FFF2F2F2'
}
};
}
currentRow
++
;
hasData
=
true
;
}
}
if
(
!
hasData
)
{
worksheet
.
getCell
(
'A3'
).
value
=
'暂无荣誉数据'
;
worksheet
.
getCell
(
'A3'
).
alignment
=
{
horizontal
:
'center'
,
vertical
:
'middle'
};
}
else
{
// 设置边框
for
(
let
row
=
2
;
row
<=
currentRow
;
row
++
)
{
for
(
let
col
=
1
;
col
<=
5
;
col
++
)
{
const
cell
=
worksheet
.
getCell
(
row
,
col
);
cell
.
border
=
{
top
:
{
style
:
'thin'
},
left
:
{
style
:
'thin'
},
bottom
:
{
style
:
'thin'
},
right
:
{
style
:
'thin'
}
};
}
}
}
console
.
log
(
`荣誉奖项工作表创建完成,共
${
dataList
.
length
-
1
}
条数据`
);
}
/**
* 获取企业信息
*/
async
function
getEnterpriseInfo
(
eId
:
string
):
Promise
<
any
>
{
try
{
// 根据你的数据库结构调整查询
const
enterpriseInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
'enterprise'
,
// 或者你的企业表名
{
eId
},
[
'enterpriseName'
]
// 可能的名称字段
);
if
(
!
enterpriseInfo
)
{
console
.
warn
(
`未找到企业信息:
${
eId
}
`
);
return
null
;
}
console
.
log
(
`获取到企业信息:`
,
enterpriseInfo
);
return
enterpriseInfo
;
}
catch
(
error
)
{
console
.
error
(
`获取企业信息失败:
${
eId
}
`
,
error
);
return
null
;
}
}
/**
* 清理文件名中的非法字符
*/
function
sanitizeFileName
(
fileName
:
string
):
string
{
if
(
!
fileName
)
return
'未知企业'
;
// 移除或替换文件名中的非法字符
return
fileName
.
replace
(
/
[
<>:"
/\\
|?*
]
/g
,
'_'
)
// 替换Windows非法字符
.
replace
(
/
\s
+/g
,
' '
)
// 合并多个空格
.
trim
()
// 去除首尾空格
.
substring
(
0
,
100
);
// 限制长度避免过长
}
/**
* 验证并记录文件信息
*/
async
function
validateAndLogFiles
(
files
:
{
url
:
string
,
fileName
:
string
}[],
category
:
string
)
{
console
.
log
(
`\n===
${
category
}
文件验证 ===`
);
console
.
log
(
`总数:
${
files
.
length
}
个文件`
);
let
existingCount
=
0
;
for
(
const
file
of
files
)
{
console
.
log
(
`文件:
${
file
.
fileName
}
`
);
console
.
log
(
`URL:
${
file
.
url
}
`
);
// 检查文件是否存在
const
exists
=
await
checkFileExists
(
file
.
url
);
console
.
log
(
`存在性:
${
exists
?
'存在'
:
'不存在'
}
`
);
if
(
exists
)
{
existingCount
++
;
}
console
.
log
(
'---'
);
}
console
.
log
(
`
${
category
}
文件统计: 存在
${
existingCount
}
/
${
files
.
length
}
个文件`
);
return
existingCount
;
}
/**
* 改进的下载函数 - 跳过不存在的文件
*/
async
function
downloadAndSaveFiles
(
files
:
{
url
:
string
,
fileName
:
string
}[],
targetDir
:
string
,
baseTempDir
:
string
):
Promise
<
void
>
{
if
(
files
.
length
===
0
)
{
console
.
log
(
`没有文件需要下载到目录:
${
targetDir
}
`
);
return
;
}
await
fs
.
ensureDir
(
targetDir
);
// 先检查所有文件的存在性
const
validFiles
:
{
url
:
string
,
fileName
:
string
}[]
=
[];
for
(
const
file
of
files
)
{
const
exists
=
await
checkFileExists
(
file
.
url
);
if
(
exists
)
{
validFiles
.
push
(
file
);
console
.
log
(
`✅ 文件可用:
${
file
.
fileName
}
`
);
}
else
{
console
.
warn
(
`❌ 文件不存在,跳过:
${
file
.
fileName
}
(
${
file
.
url
}
)`
);
}
}
console
.
log
(
`有效文件数量:
${
validFiles
.
length
}
/
${
files
.
length
}
`
);
if
(
validFiles
.
length
===
0
)
{
console
.
log
(
`没有可下载的有效文件,跳过目录:
${
targetDir
}
`
);
return
;
}
// 只下载存在的文件
const
downloadPromises
=
validFiles
.
map
(
async
(
file
)
=>
{
try
{
if
(
!
file
.
url
||
typeof
file
.
url
!==
'string'
)
{
console
.
warn
(
`文件URL无效:`
,
file
.
url
);
return
;
}
console
.
log
(
`开始下载文件:
${
file
.
fileName
}
from
${
file
.
url
}
`
);
const
fetchOptions
:
any
=
{
method
:
'GET'
,
timeout
:
30000
,
headers
:
{
'User-Agent'
:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
,
'Accept'
:
'*/*'
}
};
// 关键修复:添加认证 token
const
SECRET_TOKEN
=
"Ngz86cuAKxblwXR9OiKSWbfkj7oZ8R0lMU8pTfpVYBDCkvtUb0ZwbaBvwWyfv2O9"
;
// 如果是内部文件服务器的URL,添加认证token
if
(
file
.
url
.
includes
(
'192.168.0.71'
)
||
file
.
url
.
includes
(
'fh.tninnopark.cn'
))
{
fetchOptions
.
headers
[
'token'
]
=
SECRET_TOKEN
;
console
.
log
(
`添加认证token到请求头`
);
}
const
response
=
await
fetch
(
file
.
url
,
fetchOptions
);
if
(
!
response
.
ok
)
{
console
.
warn
(
`下载文件失败:
${
file
.
url
}
, 状态码:
${
response
.
status
}
`
);
return
;
}
const
buffer
=
await
response
.
buffer
();
if
(
buffer
.
length
===
0
)
{
console
.
warn
(
`文件内容为空:
${
file
.
fileName
}
`
);
return
;
}
const
filePath
=
path
.
join
(
targetDir
,
file
.
fileName
);
await
fs
.
writeFile
(
filePath
,
buffer
);
console
.
log
(
`✅ 文件下载成功:
${
file
.
fileName
}
, 大小:
${
buffer
.
length
}
bytes`
);
}
catch
(
error
)
{
console
.
error
(
`下载文件失败:
${
file
.
fileName
}
(
${
file
.
url
}
)`
,
error
.
message
);
}
});
const
results
=
await
Promise
.
allSettled
(
downloadPromises
);
const
successful
=
results
.
filter
(
result
=>
result
.
status
===
'fulfilled'
).
length
;
const
failed
=
results
.
filter
(
result
=>
result
.
status
===
'rejected'
).
length
;
console
.
log
(
`目录
${
targetDir
}
下载完成: 成功
${
successful
}
个, 失败
${
failed
}
个, 总共
${
validFiles
.
length
}
个有效文件`
);
}
/**
* 检查文件是否存在于文件服务器
*/
async
function
checkFileExists
(
url
:
string
):
Promise
<
boolean
>
{
try
{
const
SECRET_TOKEN
=
"Ngz86cuAKxblwXR9OiKSWbfkj7oZ8R0lMU8pTfpVYBDCkvtUb0ZwbaBvwWyfv2O9"
;
const
fetchOptions
:
any
=
{
method
:
'HEAD'
,
timeout
:
10000
,
headers
:
{
'User-Agent'
:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
};
// 同样为HEAD请求添加认证token
if
(
url
.
includes
(
'192.168.0.71'
)
||
url
.
includes
(
'fh.tninnopark.cn'
))
{
fetchOptions
.
headers
[
'token'
]
=
SECRET_TOKEN
;
}
const
response
=
await
fetch
(
url
,
fetchOptions
);
return
response
.
ok
;
}
catch
(
error
)
{
console
.
log
(
`文件存在性检查失败:
${
url
}
`
,
error
.
message
);
return
false
;
}
}
/**
* 安全的URL构建函数,避免中文编码问题
*/
function
buildSafeUrl
(
baseUrl
:
string
,
filePath
:
string
):
string
{
// 确保基础URL格式正确
const
cleanBaseUrl
=
baseUrl
.
endsWith
(
'/'
)
?
baseUrl
.
slice
(
0
,
-
1
)
:
baseUrl
;
// 确保文件路径格式正确
const
cleanFilePath
=
filePath
.
startsWith
(
'/'
)
?
filePath
:
`/
${
filePath
}
`
;
// 直接拼接,避免URL对象的自动编码
return
`
${
cleanBaseUrl
}${
cleanFilePath
}
`
;
}
/**
* 统一处理文件路径,将相对路径转换为绝对URL
* 修复中文文件名编码问题
* http://192.168.0.71:9097
* https://fh.tninnopark.cn
*/
function
processFilePath
(
filePath
:
any
,
baseUrl
:
string
=
'http://192.168.0.71:9097'
):
string
|
null
{
if
(
!
filePath
)
{
console
.
log
(
'文件路径为空'
);
return
null
;
}
console
.
log
(
`原始文件路径:
${
filePath
}
, 类型:
${
typeof
filePath
}
`
);
// 如果是数组,取第一个元素
if
(
Array
.
isArray
(
filePath
))
{
filePath
=
filePath
[
0
];
}
// 处理JSON字符串格式
if
(
typeof
filePath
===
'string'
&&
filePath
.
startsWith
(
'['
))
{
try
{
const
pathArray
=
JSON
.
parse
(
filePath
);
filePath
=
pathArray
[
0
];
console
.
log
(
`解析JSON数组路径:
${
filePath
}
`
);
}
catch
(
e
)
{
console
.
warn
(
'解析文件路径数组失败:'
,
filePath
);
return
null
;
}
}
// 验证路径格式
if
(
!
filePath
||
typeof
filePath
!==
'string'
)
{
return
null
;
}
// 如果已经是完整的URL,直接返回
if
(
filePath
.
startsWith
(
'http://'
)
||
filePath
.
startsWith
(
'https://'
))
{
return
filePath
;
}
// 格式化基础URL
const
formattedBaseUrl
=
baseUrl
.
endsWith
(
'/'
)
?
baseUrl
.
slice
(
0
,
-
1
)
:
baseUrl
;
// 关键修复:确保路径格式正确且中文不被编码
let
finalPath
=
filePath
;
if
(
!
finalPath
.
startsWith
(
'/'
))
{
finalPath
=
'/'
+
finalPath
;
}
// 构建完整的URL(不对路径部分进行编码)
const
url
=
new
URL
(
formattedBaseUrl
);
url
.
pathname
=
finalPath
;
const
fullUrl
=
buildSafeUrl
(
baseUrl
,
finalPath
);
console
.
log
(
`安全构建的URL:
${
fullUrl
}
`
);
return
fullUrl
;
}
/**
* 获取租赁信息相关文件
*/
async
function
getLeaseFiles
(
eId
:
string
):
Promise
<
{
url
:
string
,
fileName
:
string
}[]
>
{
const
filesList
=
[
"sanFangXieYi"
,
"fuHuaXieYi"
,
"fangWuZuLing"
,
"fuHuaXieYiBuChong"
,
"chengXinChengNuoHan"
,
"yingYeZhiZhao"
,
"ruFuZiLiao"
,
"ruZhuJiHua"
,
"yaJinZhiFu"
,
"cardCopy"
];
const
leaseInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
TABLENAME
.
租赁信息
,
{
eId
},
filesList
);
const
files
:
{
url
:
string
,
fileName
:
string
}[]
=
[];
leaseInfo
.
forEach
(
lease
=>
{
filesList
.
forEach
(
field
=>
{
if
(
lease
[
field
])
{
const
processedUrl
=
processFilePath
(
lease
[
field
]);
if
(
processedUrl
)
{
const
fileName
=
getLeaseFileName
(
field
,
lease
);
files
.
push
({
url
:
processedUrl
,
fileName
:
fileName
});
}
}
});
});
return
files
;
}
/**
* 获取租赁文件显示名称
*/
function
getLeaseFileName
(
field
:
string
,
lease
:
any
):
string
{
const
nameMap
:
{[
key
:
string
]:
string
}
=
{
sanFangXieYi
:
'三方协议'
,
fuHuaXieYi
:
'孵化协议'
,
fangWuZuLing
:
'房屋租赁合同'
,
fuHuaXieYiBuChong
:
'孵化协议补充协议书'
,
chengXinChengNuoHan
:
'诚信承诺函'
,
yingYeZhiZhao
:
'营业执照复印件'
,
ruFuZiLiao
:
'入孵资料明细'
,
ruZhuJiHua
:
'入驻计划复印件'
,
yaJinZhiFu
:
'押金支付凭证'
,
cardCopy
:
'身份证复印件'
};
const
baseName
=
nameMap
[
field
]
||
field
;
// 获取实际的文件扩展名
let
extension
=
''
;
if
(
lease
[
field
]
&&
typeof
lease
[
field
]
===
'string'
)
{
const
processedUrl
=
processFilePath
(
lease
[
field
]);
if
(
processedUrl
)
{
const
ext
=
path
.
extname
(
processedUrl
);
if
(
ext
)
{
extension
=
ext
;
}
else
{
// 如果没有扩展名,根据字段类型推测
if
(
field
===
'cardCopy'
||
field
===
'yingYeZhiZhao'
)
{
extension
=
'.jpg'
;
// 身份证和营业执照通常是图片
}
else
{
extension
=
'.pdf'
;
// 其他文件默认PDF
}
}
}
}
// 确保文件名安全
const
safeFileName
=
baseName
.
replace
(
/
[
<>:"
/\\
|?*
]
/g
,
'_'
);
return
`
${
safeFileName
}${
extension
}
`
;
}
/**
* 获取商标相关文件
*/
async
function
getTrademarkFiles
(
eId
:
string
):
Promise
<
{
url
:
string
,
fileName
:
string
}[]
>
{
const
trademarkInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
'trade_mark'
,
{
eId
},
[
"tmId"
,
"regNo"
,
"name"
,
"imageUrl"
]
);
const
files
:
{
url
:
string
,
fileName
:
string
}[]
=
[];
trademarkInfo
.
forEach
(
trademark
=>
{
if
(
trademark
.
imageUrl
)
{
let
processedUrl
=
processFilePath
(
trademark
.
imageUrl
);
// 特殊处理商标图片URL:移除多余的 /img 后缀
// if (processedUrl && processedUrl.endsWith('/img')) {
// processedUrl = processedUrl.slice(0, -4); // 移除最后的 '/img'
// console.log(`修复商标图片URL: ${processedUrl}`);
// }
if
(
processedUrl
)
{
const
extension
=
path
.
extname
(
processedUrl
)
||
'.jpg'
;
// 清理文件名中的特殊字符
const
safeName
=
(
trademark
.
name
||
''
).
replace
(
/
[
<>:"
/\\
|?*
]
/g
,
'_'
);
const
fileName
=
`商标_
${
trademark
.
regNo
||
trademark
.
tmId
}
_
${
safeName
}${
extension
}
`
;
files
.
push
({
url
:
processedUrl
,
fileName
:
fileName
});
}
}
});
return
files
;
}
/**
* 获取作品著作权相关文件
*/
async
function
getCopyrightFiles
(
eId
:
string
):
Promise
<
{
url
:
string
,
fileName
:
string
}[]
>
{
const
copyrightInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
'copy_right'
,
{
eId
},
[
"crId"
,
"registerNo"
,
"name"
,
"iprUrl"
]
);
const
files
:
{
url
:
string
,
fileName
:
string
}[]
=
[];
copyrightInfo
.
forEach
(
copyright
=>
{
if
(
copyright
.
iprUrl
)
{
const
processedUrl
=
processFilePath
(
copyright
.
iprUrl
);
if
(
processedUrl
)
{
const
extension
=
path
.
extname
(
processedUrl
)
||
'.pdf'
;
const
fileName
=
`作品著作权_
${
copyright
.
registerNo
||
copyright
.
crId
}
_
${
copyright
.
name
}${
extension
}
`
;
files
.
push
({
url
:
processedUrl
,
fileName
:
fileName
});
}
}
});
return
files
;
}
/**
* 获取软件著作权相关文件
*/
async
function
getSoftwareCopyrightFiles
(
eId
:
string
):
Promise
<
{
url
:
string
,
fileName
:
string
}[]
>
{
const
softwareCopyrightInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
'software_copyright'
,
{
eId
},
[
"scId"
,
"registerNo"
,
"name"
,
"iprUrl"
]
);
const
files
:
{
url
:
string
,
fileName
:
string
}[]
=
[];
softwareCopyrightInfo
.
forEach
(
software
=>
{
if
(
software
.
iprUrl
)
{
const
processedUrl
=
processFilePath
(
software
.
iprUrl
);
if
(
processedUrl
)
{
const
extension
=
path
.
extname
(
processedUrl
)
||
'.pdf'
;
const
fileName
=
`软件著作权_
${
software
.
registerNo
||
software
.
scId
}
_
${
software
.
name
}${
extension
}
`
;
files
.
push
({
url
:
processedUrl
,
fileName
:
fileName
});
}
}
});
return
files
;
}
/**
* 获取专利相关文件
*/
async
function
getPatentFiles
(
eId
:
string
):
Promise
<
{
url
:
string
,
fileName
:
string
}[]
>
{
const
patentInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询多个
,
'patent'
,
{
eId
},
[
"patentId"
,
"applicationNumber"
,
"title"
,
"iprUrl"
]
);
const
files
:
{
url
:
string
,
fileName
:
string
}[]
=
[];
patentInfo
.
forEach
(
patent
=>
{
if
(
patent
.
iprUrl
)
{
const
processedUrl
=
processFilePath
(
patent
.
iprUrl
);
if
(
processedUrl
)
{
const
extension
=
path
.
extname
(
processedUrl
)
||
'.pdf'
;
const
fileName
=
`专利_
${
patent
.
applicationNumber
||
patent
.
patentId
}
_
${
patent
.
title
}${
extension
}
`
;
files
.
push
({
url
:
processedUrl
,
fileName
:
fileName
});
}
}
});
return
files
;
}
/**
* 简单的图片文件头验证
*/
function
isValidImageHeader
(
header
:
string
):
boolean
{
const
validHeaders
=
[
'ffd8ffe0'
,
// JPEG
'ffd8ffe1'
,
// JPEG
'ffd8ffe2'
,
// JPEG
'89504e47'
,
// PNG
'47494638'
,
// GIF
'424d'
// BMP (前2字节)
];
return
validHeaders
.
some
(
valid
=>
header
.
startsWith
(
valid
));
}
/**
* 创建ZIP压缩包
*/
async
function
createZipArchive
(
sourceDir
:
string
,
outPath
:
string
):
Promise
<
void
>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
const
output
=
fs
.
createWriteStream
(
outPath
);
const
archive
=
archiver
(
'zip'
,
{
zlib
:
{
level
:
9
}
// 最高压缩级别
});
output
.
on
(
'close'
,
()
=>
{
console
.
log
(
`ZIP文件创建完成:
${
outPath
}
, 大小:
${
archive
.
pointer
()}
bytes`
);
resolve
();
});
archive
.
on
(
'error'
,
(
err
)
=>
{
reject
(
err
);
});
archive
.
pipe
(
output
);
archive
.
directory
(
sourceDir
,
false
);
archive
.
finalize
();
});
}
src/biz/ledger.ts
View file @
936cbd63
...
...
@@ -130,7 +130,7 @@ import { AdminRegisterUpdateConfig } from "../config/eccParam/enterprise";
* @param page
* @returns {dataList, dataCount} 数据列表, 数据总数
*/
export
async
function
ledgerList
(
enterpriseName
:
string
,
logonStartTime
:
Number
,
logonEndTime
:
Number
,
building
:
number
,
page
:
number
)
{
export
async
function
ledgerList
(
enterpriseName
:
string
,
phone
:
string
,
logonStartTime
:
Number
,
logonEndTime
:
Number
,
building
:
number
,
page
:
number
)
{
let
selectParam
:
any
=
{
state
:
enumConfig
.
CHANGESTATE
.
已通过
};
if
(
enterpriseName
)
{
selectParam
.
enterpriseName
=
{
"%like%"
:
enterpriseName
};
...
...
@@ -139,11 +139,17 @@ export async function ledgerList(enterpriseName:string, logonStartTime:Number, l
selectParam
.
logonTime
=
{
"%between%"
:[
getMySqlMs
(
logonStartTime
),
getMySqlMs
(
logonEndTime
)]}
}
let
userSelectParam
:
any
=
{};
if
(
phone
)
{
userSelectParam
.
phone
=
{
"%like%"
:
phone
};;
}
// 主表字段过滤参数保持不变
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"logonAddress"
,
"qiYeGuiMo"
];
let
manyTableInfo
:
any
=
{};
let
rufuSelectParam
=
{
state
:
{
"%between%"
:
[
enumConfig
.
FUHUASTATE
.
实体孵化
,
enumConfig
.
FUHUASTATE
.
虚拟孵化
]
}
};
manyTableInfo
[
TABLENAME
.
企业孵化信息
]
=
{
column
:[
"moveOutTime"
,
"moveOutType"
,
"startTime"
,
"endTime"
],
where
:
rufuSelectParam
};
manyTableInfo
[
TABLENAME
.
企业用户表
]
=
{
column
:[
"userName"
,
"phone"
],
where
:
userSelectParam
};
let
resInfo
=
await
selectManyTableData
(
OPERATIONALDATATYPE
.
多表联查
,
TABLENAME
.
企业基础信息表
,
selectParam
,
filesList
,
manyTableInfo
);
/**查询租赁表信息 */
...
...
@@ -260,6 +266,7 @@ export async function ledgerList(enterpriseName:string, logonStartTime:Number, l
logonAddress
,
qiYeGuiMo
,
enterprise_fuhuas
,
enterprise_users
,
}
=
info
;
// 过滤条件:如果没有租赁信息,跳过
...
...
@@ -288,10 +295,17 @@ export async function ledgerList(enterpriseName:string, logonStartTime:Number, l
知识产权总数
:
0
};
// 获取企业登录信息
let
phone
=
"-"
;
if
(
enterprise_users
[
0
]?.
phone
)
{
phone
=
enterprise_users
[
0
]?.
phone
;
}
zaifuList
.
push
({
eId
,
enterpriseName
,
// 企业名称
uscc
,
// 统一信用代码
phone
,
//登录手机号
logonTime
:
moment
(
logonTime
).
format
(
"YYYY-MM-DD"
),
// 注册日期
logonAddress
:
changeAdd
(
JSON
.
parse
(
logonAddress
)),
// 注册地址
qiYeGuiMo
,
// 企业规模
...
...
src/biz/mail.ts
View file @
936cbd63
...
...
@@ -127,8 +127,8 @@ function getModel(name, type, otherStr?, code?) {
if
(
!
userInfo
.
mail
)
{
new
BizError
(
ERRORENUM
.
该用户邮箱为空
,
eId
,
eId
.
enterpriseName
);
}
else
{
//
let result = await send(userInfo.mail, userInfo.enterpriseName, type, otherStr);
let
result
=
"邮件发送成功"
let
result
=
await
send
(
userInfo
.
mail
,
userInfo
.
enterpriseName
,
type
,
otherStr
);
//
let result = "邮件发送成功"
}
return
successResult
();
...
...
src/biz/ruFu.ts
View file @
936cbd63
...
...
@@ -162,8 +162,212 @@ export async function settleInEnterpriseList(page:number, enterpriseName:string)
* @param eId
* @returns
*/
export
async
function
settleInEnterprisePass
(
eId
:
string
)
{
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"state"
];
// export async function settleInEnterprisePass(eId:string) {
// let filesList = ["eId", "enterpriseName", "uscc", "logonTime", "state"];
// let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList);
// if (!resInfo || !resInfo.eId) {
// throw new BizError(ERRORENUM.数据不存在);
// }
// let updateInfo = {
// register:enumConfig.CHANGESTATE.已通过,
// randomCode:randomCode(),
// isNewApplication: enumConfig.STATE.是,
// }
// await operationalData(OPERATIONALDATATYPE.修改, TABLENAME.企业基础信息表, updateInfo, {eId});
// let addInfo = {
// approvalId: randomId(TABLEID.入孵申请审批表),
// eId,
// changeType: enumConfig.CHANGETYPE.入孵申请,
// changeState: enumConfig.CHANGESTATE.已通过,
// createTimeMs: getMySqlMs()
// }
// await operationalData( OPERATIONALDATATYPE.增加, TABLENAME.入孵申请审批表, addInfo, {} );
// //发送邮件
// await systemSendMail(eId, enumConfig.MAILTYPE.通过入孵申请 );
// return {isSuccess:true};
// }
/**
* 入孵申请通过
* @param eId
* @returns
*/
// export async function settleInEnterprisePass(eId:string) {
// let filesList = ["eId", "enterpriseName", "uscc", "logonTime", "state", "emailReminder"];
// let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList);
// if (!resInfo || !resInfo.eId) {
// throw new BizError(ERRORENUM.数据不存在);
// }
// let updateInfo = {
// register:enumConfig.CHANGESTATE.已通过,
// randomCode:randomCode(),
// isNewApplication: enumConfig.STATE.是,
// }
// await operationalData(OPERATIONALDATATYPE.修改, TABLENAME.企业基础信息表, updateInfo, {eId});
// let addInfo = {
// approvalId: randomId(TABLEID.入孵申请审批表),
// eId,
// changeType: enumConfig.CHANGETYPE.入孵申请,
// changeState: enumConfig.CHANGESTATE.已通过,
// createTimeMs: getMySqlMs()
// }
// await operationalData( OPERATIONALDATATYPE.增加, TABLENAME.入孵申请审批表, addInfo, {} );
// //发送邮件
// await systemSendMail(eId, enumConfig.MAILTYPE.通过入孵申请);
// // 如果emailReminder为"是",设置7天后检查是否提交入孵材料的周期性提醒
// if (resInfo.emailReminder == enumConfig.STATE.是) {
// // 创建一个递归函数,用于周期性检查
// const scheduleReminderCheck = async () => {
// try {
// // 检查是否应该继续提醒
// const shouldContinue = await checkShouldContinue(eId);
// if (!shouldContinue) {
// console.log(`为企业 ${eId} 停止周期性入孵材料提交提醒,时间:${new Date().toLocaleString()}`);
// return; // 终止循环
// }
// // 检查企业是否已提交入孵材料(即是否有入孵材料审批记录)
// const materialCheck = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.入孵申请审批表,
// {
// eId,
// changeType: enumConfig.CHANGETYPE.入孵材料审批
// },
// ["approvalId"]
// );
// // 如果没有入孵材料审批记录,说明企业尚未提交入孵材料,发送提醒邮件
// if (!materialCheck || !materialCheck.approvalId) {
// const mailStr = `
// <p>感谢贵公司对【雨艺孵化器】的关注与信任。经我们初步审核,贵公司提交的入孵申请已通过<span style='font-weight: 700;'>初审</span>。为推进下一阶段工作,请贵方协助完成以下事项:</p>
// <p><span style='font-weight: 700;'>*电脑端:</span>通过点击链接上传入孵材料:</p>
// <p>https://fh.tninnopark.cn/incubatorApply</p>
// <p><span style='font-weight: 700;'>*手机端:</span>通过扫码上传入孵材料:</p>
// <p><img src='https://fh.tninnopark.cn/yuyi/files/域名访问.png' /></p>
// <p><span style='font-weight: 700;'>下一步事项:</span></p>
// <p>如涉及提交实物材料(如:入驻计划复印件、孵化协议等),携带公司证明材料前往4-1201。</p>
// <p>我们期待与贵公司的进一步合作,共同推动项目成长与落地</p>
// <p>再次感谢您的积极参与!</p>
// <p style='text-align: right;'>祝 商祺!</p>
// <p style='text-align: right;'>雨艺孵化器</p>
// `;
// // 发送提醒邮件
// await systemSendMail(eId, enumConfig.MAILTYPE.通过入孵申请, mailStr);
// console.log(`入孵材料提交提醒邮件已发送给企业 ${eId},时间:${new Date().toLocaleString()}`);
// } else {
// console.log(`企业 ${eId} 已提交入孵材料,无需发送提醒邮件,时间:${new Date().toLocaleString()}`);
// }
// // 7天后再次检查(无论是否发送邮件)
// setTimeout(scheduleReminderCheck, 7 * 24 * 60 * 60 * 1000);
// } catch (error) {
// console.error(`检查并发送入孵材料提交提醒邮件失败:`, error);
// // 即使出错,7天后也重试
// setTimeout(scheduleReminderCheck, 7 * 24 * 60 * 60 * 1000);
// }
// };
// // 辅助函数:检查是否应该继续提醒
// const checkShouldContinue = async (enterpriseId: string): Promise<boolean> => {
// try {
// // 1. 检查企业是否已提交入孵材料
// const materialCheck = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.入孵申请审批表,
// {
// eId: enterpriseId,
// changeType: enumConfig.CHANGETYPE.入孵材料审批
// },
// ["approvalId"]
// );
// if (materialCheck && materialCheck.approvalId) {
// console.log(`企业 ${enterpriseId} 已提交入孵材料,符合终止条件`);
// return false; // 已提交材料,停止提醒
// }
// // 2. 检查企业是否已通过入孵材料审核(state = 已通过)
// const enterpriseInfo = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.企业基础信息表,
// { eId: enterpriseId },
// ["state", "emailReminder"]
// );
// if (!enterpriseInfo) {
// console.log(`企业 ${enterpriseId} 信息不存在,停止提醒`);
// return false; // 企业不存在,停止提醒
// }
// // 如果企业已通过入孵材料审核
// if (enterpriseInfo.state == enumConfig.CHANGESTATE.已通过) {
// console.log(`企业 ${enterpriseId} 已通过入孵材料审核,符合终止条件`);
// return false; // 已通过审核,停止提醒
// }
// // 3. 检查企业是否关闭了邮件提醒
// if (enterpriseInfo.emailReminder != enumConfig.STATE.是) {
// console.log(`企业 ${enterpriseId} 已关闭邮件提醒,符合终止条件`);
// return false; // 已关闭提醒,停止
// }
// // 4. 检查企业是否被驳回(如果被驳回,也不应该继续提醒提交材料)
// const rejectedCheck = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.入孵申请审批表,
// {
// eId: enterpriseId,
// changeType: enumConfig.CHANGETYPE.入孵申请,
// changeState: enumConfig.CHANGESTATE.已驳回
// },
// ["approvalId"]
// );
// if (rejectedCheck && rejectedCheck.approvalId) {
// console.log(`企业 ${enterpriseId} 的入孵申请已被驳回,停止提醒`);
// return false; // 申请被驳回,停止提醒
// }
// // 所有检查通过,继续提醒
// return true;
// } catch (error) {
// console.error(`检查终止条件失败,企业ID: ${enterpriseId}`, error);
// return true; // 出错时默认继续,避免因临时错误而停止
// }
// };
// // 7天后开始第一次检查
// setTimeout(scheduleReminderCheck, 7 * 24 * 60 * 60 * 1000);
// console.log(`已为企业 ${eId} 设置周期性入孵材料提交提醒,首次检查将在7天后进行`);
// }
// return {isSuccess:true};
// }
/**
* 入孵申请通过
* @param eId 企业ID
* @param production 环境标识:"production"表示生产环境,其他表示测试环境
* @returns
*/
export
async
function
settleInEnterprisePass
(
eId
:
string
,
production
:
string
=
"test"
)
{
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"state"
,
"emailReminder"
];
let
resInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业基础信息表
,
{
eId
},
filesList
);
if
(
!
resInfo
||
!
resInfo
.
eId
)
{
...
...
@@ -187,12 +391,172 @@ export async function settleInEnterprisePass(eId:string) {
await
operationalData
(
OPERATIONALDATATYPE
.
增加
,
TABLENAME
.
入孵申请审批表
,
addInfo
,
{}
);
//发送邮件
await
systemSendMail
(
eId
,
enumConfig
.
MAILTYPE
.
通过入孵申请
);
await
systemSendMail
(
eId
,
enumConfig
.
MAILTYPE
.
通过入孵申请
);
// 如果emailReminder为"是",设置周期性提醒机制
if
(
resInfo
.
emailReminder
==
enumConfig
.
STATE
.
是
)
{
// 根据参数确定提醒间隔
const
REMINDER_INTERVAL
=
production
===
"production"
?
7
*
24
*
60
*
60
*
1000
// 生产环境:7天
:
60
*
1000
;
// 测试环境:1分钟
// 创建一个递归函数,用于周期性检查
const
scheduleReminderCheck
=
async
()
=>
{
try
{
// 检查是否应该继续提醒
const
shouldContinue
=
await
checkShouldContinue
(
eId
);
if
(
!
shouldContinue
)
{
console
.
log
(
`为企业
${
eId
}
停止周期性入孵材料提交提醒,时间:
${
new
Date
().
toLocaleString
()}
`
);
return
;
// 终止循环
}
// 检查企业是否已提交入孵材料(即是否有入孵材料审批记录)
const
materialCheck
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
入孵申请审批表
,
{
eId
,
changeType
:
enumConfig
.
CHANGETYPE
.
入孵材料审批
},
[
"approvalId"
]
);
// 如果没有入孵材料审批记录,说明企业尚未提交入孵材料,发送提醒邮件
if
(
!
materialCheck
||
!
materialCheck
.
approvalId
)
{
const
mailStr
=
`
<p>感谢贵公司对【雨艺孵化器】的关注与信任。经我们初步审核,贵公司提交的入孵申请已通过<span style='font-weight: 700;'>初审</span>。为推进下一阶段工作,请贵方协助完成以下事项:</p>
<p><span style='font-weight: 700;'>*电脑端:</span>通过点击链接上传入孵材料:</p>
<p>https://fh.tninnopark.cn/incubatorApply</p>
<p><span style='font-weight: 700;'>*手机端:</span>通过扫码上传入孵材料:</p>
<p><img src='https://fh.tninnopark.cn/yuyi/files/域名访问.png' /></p>
<p><span style='font-weight: 700;'>下一步事项:</span></p>
<p>如涉及提交实物材料(如:入驻计划复印件、孵化协议等),携带公司证明材料前往4-1201。</p>
<p>我们期待与贵公司的进一步合作,共同推动项目成长与落地</p>
<p>再次感谢您的积极参与!</p>
<p style='text-align: right;'>祝 商祺!</p>
<p style='text-align: right;'>雨艺孵化器</p>
`
;
// 发送提醒邮件
await
systemSendMail
(
eId
,
enumConfig
.
MAILTYPE
.
通过入孵申请
,
mailStr
);
console
.
log
(
`入孵材料提交提醒邮件已发送给企业
${
eId
}
,时间:
${
new
Date
().
toLocaleString
()}
,环境:
${
production
}
`
);
}
else
{
console
.
log
(
`企业
${
eId
}
已提交入孵材料,无需发送提醒邮件,时间:
${
new
Date
().
toLocaleString
()}
`
);
}
// 设置下一次检查(无论是否发送邮件)
setTimeout
(
scheduleReminderCheck
,
REMINDER_INTERVAL
);
}
catch
(
error
)
{
console
.
error
(
`检查并发送入孵材料提交提醒邮件失败:`
,
error
);
// 即使出错,也尝试设置下一次检查
setTimeout
(
scheduleReminderCheck
,
REMINDER_INTERVAL
);
}
};
// 辅助函数:检查是否应该继续提醒
const
checkShouldContinue
=
async
(
enterpriseId
:
string
):
Promise
<
boolean
>
=>
{
try
{
// 1. 检查企业是否已提交入孵材料
const
materialCheck
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
入孵申请审批表
,
{
eId
:
enterpriseId
,
changeType
:
enumConfig
.
CHANGETYPE
.
入孵材料审批
},
[
"approvalId"
]
);
if
(
materialCheck
&&
materialCheck
.
approvalId
)
{
console
.
log
(
`企业
${
enterpriseId
}
已提交入孵材料,符合终止条件`
);
return
false
;
// 已提交材料,停止提醒
}
// 2. 检查企业是否已通过入孵材料审核(state = 已通过)
const
enterpriseInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业基础信息表
,
{
eId
:
enterpriseId
},
[
"state"
,
"emailReminder"
]
);
if
(
!
enterpriseInfo
)
{
console
.
log
(
`企业
${
enterpriseId
}
信息不存在,停止提醒`
);
return
false
;
// 企业不存在,停止提醒
}
// 如果企业已通过入孵材料审核
if
(
enterpriseInfo
.
state
==
enumConfig
.
CHANGESTATE
.
已通过
)
{
console
.
log
(
`企业
${
enterpriseId
}
已通过入孵材料审核,符合终止条件`
);
return
false
;
// 已通过审核,停止提醒
}
// 3. 检查企业是否关闭了邮件提醒
if
(
enterpriseInfo
.
emailReminder
!=
enumConfig
.
STATE
.
是
)
{
console
.
log
(
`企业
${
enterpriseId
}
已关闭邮件提醒,符合终止条件`
);
return
false
;
// 已关闭提醒,停止
}
// 4. 检查企业是否被驳回(如果被驳回,也不应该继续提醒提交材料)
const
rejectedCheck
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
入孵申请审批表
,
{
eId
:
enterpriseId
,
changeType
:
enumConfig
.
CHANGETYPE
.
入孵申请
,
changeState
:
enumConfig
.
CHANGESTATE
.
已驳回
},
[
"approvalId"
]
);
if
(
rejectedCheck
&&
rejectedCheck
.
approvalId
)
{
console
.
log
(
`企业
${
enterpriseId
}
的入孵申请已被驳回,停止提醒`
);
return
false
;
// 申请被驳回,停止提醒
}
// 5. 检查企业是否已迁出
const
movedOutCheck
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业孵化信息
,
{
eId
:
enterpriseId
},
[
"state"
]
);
if
(
movedOutCheck
&&
movedOutCheck
.
state
==
enumConfig
.
FUHUASTATE
.
迁出
)
{
console
.
log
(
`企业
${
enterpriseId
}
已迁出,停止提醒`
);
return
false
;
// 企业已迁出,停止提醒
}
// 所有检查通过,继续提醒
return
true
;
}
catch
(
error
)
{
console
.
error
(
`检查终止条件失败,企业ID:
${
enterpriseId
}
`
,
error
);
// 出错时默认继续提醒,避免因临时错误而停止
return
true
;
}
};
// 记录提醒设置信息
console
.
log
(
`已为企业
${
eId
}
设置周期性入孵材料提交提醒`
,
{
企业名称
:
resInfo
.
enterpriseName
,
环境模式
:
production
,
提醒间隔
:
`
${
REMINDER_INTERVAL
}
ms (
${
REMINDER_INTERVAL
/
(
60
*
1000
)}
分钟)`
,
首次提醒时间
:
new
Date
(
Date
.
now
()
+
REMINDER_INTERVAL
).
toLocaleString
()
});
// 设置第一次检查
setTimeout
(
scheduleReminderCheck
,
REMINDER_INTERVAL
);
}
return
{
isSuccess
:
true
};
}
/**
* 入孵申请回显
* @param eId
...
...
@@ -308,6 +672,88 @@ export async function settleInEnterpriseUpdate(eId:string, param) {
* @param desc
* @returns
*/
// export async function settleInEnterpriseOut(eId:string, descType, desc:string) {
// let filesList = ["eId", "enterpriseName", "uscc", "logonTime", "state", "emailReminder"];
// let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList);
// if (!resInfo || !resInfo.eId) {
// throw new BizError(ERRORENUM.数据不存在);
// }
// let params = {
// register: enumConfig.CHANGESTATE.已驳回,
// // isNewApplication: enumConfig.STATE.否
// };
// await operationalData( OPERATIONALDATATYPE.修改, TABLENAME.企业基础信息表, params, { eId });
// let descStr = "";
// for(let i = 0; i < descType.length; i++) {
// if (descType[i] == enumConfig.DESCTYPE.其他) {
// if (desc) descStr += `${desc};`
// } else {
// descStr += `${changeEnumValue(enumConfig.DESCTYPE, descType[i])};`;
// }
// }
// let descTypeStr = JSON.stringify(descType) || '[]';
// let addInfo = {
// approvalId: randomId(TABLEID.入孵申请审批表),
// eId,
// changeType: enumConfig.CHANGETYPE.入孵申请,
// changeState: enumConfig.CHANGESTATE.已驳回,
// createTimeMs: getMySqlMs(),
// descType:descTypeStr,
// desc:descStr,
// }
// await operationalData( OPERATIONALDATATYPE.增加, TABLENAME.入孵申请审批表, addInfo, {} );
// /**发送邮件 */
// let mailStr = "";
// mailStr += "<p>感谢贵公司对【雨艺孵化器】的关注与信任。经我们初步审核,遗憾地通知您,贵公司此次入孵申请<span style='font-weight: 700;'>未通过初审</span>。主要原因为:</p>";
// mailStr += `<ul>`;
// mailStr += `<li>${descStr}</li>`;
// mailStr += `</ul>`;
// mailStr += `<p>以上内容仅作为此次审核意见供参考,您可根据反馈进行优化调整。如后续有相关优化材料或补充说明,欢迎重新提交申请。</p>`;
// mailStr += `<p>我们期待未来与贵公司的合作机会,衷心祝愿贵公司业务发展顺利!</p>`;
// await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵申请, mailStr );
// /**如果emailReminder为是,则设置7天后再次提醒 */
// if (resInfo.emailReminder == enumConfig.STATE.是) {
// setTimeout( async() => {
// try {
// //检查企业状态是否仍然是已驳回(未重新提交)
// let currentInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, ["register"]);
// if (currentInfo && currentInfo.register === enumConfig.CHANGESTATE.已驳回) {
// let reminderMailStr = "";
// reminderMailStr += "<p>【雨艺孵化器】入孵申请提醒</p>";
// reminderMailStr += "<p>尊敬的客户:</p>";
// reminderMailStr += "<p>我们注意到您在7天前提交的入孵申请未通过初审,目前尚未收到您的重新提交。</p>";
// reminderMailStr += `<p>驳回原因:${descStr}</p>`;
// reminderMailStr += "<p>如果您仍有入驻意向,请根据审核意见完善资料后重新提交申请。</p>";
// reminderMailStr += "<p>如有任何疑问,欢迎随时联系我们。</p>";
// reminderMailStr += "<p>期待您的回复!</p>";
// await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵申请, reminderMailStr);
// console.log(`7天后入孵申请驳回提醒邮件已发送给企业 ${resInfo.eId}`);
// }
// } catch (error) {
// console.error(`发送7天后入孵申请驳回提醒邮件失败:`, error);
// }
// }, 7 * 24 * 60 * 60 * 1000); // 7天后的毫秒数
// }
// return {isSuccess:true};
// }
/**
* 入孵申请驳回
* @param eId 企业ID
* @param descType 驳回类型 [1, 2]
* @param desc 驳回原因
* @param production 环境标识:"production"表示生产环境,其他表示测试环境
* @returns
*/
export
async
function
settleInEnterpriseOut
(
eId
:
string
,
descType
,
desc
:
string
)
{
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"state"
,
"emailReminder"
];
let
resInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业基础信息表
,
{
eId
},
filesList
);
...
...
@@ -353,36 +799,333 @@ export async function settleInEnterpriseOut(eId:string, descType, desc:string) {
mailStr
+=
`<p>我们期待未来与贵公司的合作机会,衷心祝愿贵公司业务发展顺利!</p>`
;
await
systemSendMail
(
resInfo
.
eId
,
enumConfig
.
MAILTYPE
.
驳回入孵申请
,
mailStr
);
/**如果emailReminder为是,则设置7天后再次提醒 */
if
(
resInfo
.
emailReminder
==
enumConfig
.
STATE
.
是
)
{
setTimeout
(
async
()
=>
{
try
{
//检查企业状态是否仍然是已驳回(未重新提交)
let
currentInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业基础信息表
,
{
eId
},
[
"register"
]);
if
(
currentInfo
&&
currentInfo
.
register
===
enumConfig
.
CHANGESTATE
.
已驳回
)
{
let
reminderMailStr
=
""
;
reminderMailStr
+=
"<p>【雨艺孵化器】入孵申请提醒</p>"
;
reminderMailStr
+=
"<p>尊敬的客户:</p>"
;
reminderMailStr
+=
"<p>我们注意到您在7天前提交的入孵申请未通过初审,目前尚未收到您的重新提交。</p>"
;
reminderMailStr
+=
`<p>驳回原因:
${
descStr
}
</p>`
;
reminderMailStr
+=
"<p>如果您仍有入驻意向,请根据审核意见完善资料后重新提交申请。</p>"
;
reminderMailStr
+=
"<p>如有任何疑问,欢迎随时联系我们。</p>"
;
reminderMailStr
+=
"<p>期待您的回复!</p>"
;
/**如果emailReminder为是,则设置周期性提醒机制 */
// if (resInfo.emailReminder == enumConfig.STATE.是) {
// // 根据参数确定提醒间隔
// const REMINDER_INTERVAL = production === "production"
// ? 7 * 24 * 60 * 60 * 1000 // 生产环境:7天
// : 60 * 1000; // 测试环境:1分钟
// // 创建申请驳回的周期性提醒函数
// const scheduleApplicationRejectionReminder = async () => {
// try {
// // 检查是否应该继续提醒
// const shouldContinue = await checkShouldContinueForApplicationRejection(eId);
// if (!shouldContinue) {
// console.log(`为企业 ${eId} 停止周期性入孵申请驳回提醒,时间:${new Date().toLocaleString()}`);
// return; // 终止循环
// }
await
systemSendMail
(
resInfo
.
eId
,
enumConfig
.
MAILTYPE
.
驳回入孵申请
,
reminderMailStr
);
console
.
log
(
`7天后入孵申请驳回提醒邮件已发送给企业
${
resInfo
.
eId
}
`
);
}
}
catch
(
error
)
{
console
.
error
(
`发送7天后入孵申请驳回提醒邮件失败:`
,
error
);
}
},
7
*
24
*
60
*
60
*
1000
);
// 7天后的毫秒数
}
// // 获取最新的企业状态
// const currentInfo = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.企业基础信息表,
// {eId},
// ["register"]
// );
// // 如果企业仍然是已驳回状态,发送提醒邮件
// if (currentInfo && currentInfo.register === enumConfig.CHANGESTATE.已驳回) {
// let reminderMailStr = "";
// reminderMailStr += "<p>【雨艺孵化器】入孵申请提醒</p>";
// reminderMailStr += "<p>尊敬的客户:</p>";
// reminderMailStr += `<p>我们注意到您之前在${moment().subtract(REMINDER_INTERVAL / (24 * 60 * 60 * 1000), 'days').format("YYYY-MM-DD")}提交的入孵申请未通过初审,目前尚未收到您的重新提交。</p>`;
// reminderMailStr += `<p>驳回原因:${descStr}</p>`;
// reminderMailStr += "<p>如果您仍有入驻意向,请根据审核意见完善资料后重新提交申请。</p>";
// reminderMailStr += "<p>您可以通过以下方式重新提交:</p>";
// reminderMailStr += "<p><span style='font-weight: 700;'>*电脑端:</span>https://fh.tninnopark.cn/incubatorApply</p>";
// reminderMailStr += "<p><span style='font-weight: 700;'>*手机端:</span>扫描下方二维码:</p>";
// reminderMailStr += "<p><img src='https://fh.tninnopark.cn/yuyi/files/域名访问.png' /></p>";
// reminderMailStr += "<p>如有任何疑问,欢迎随时联系我们。</p>";
// reminderMailStr += "<p>期待您的回复!</p>";
// await systemSendMail(eId, enumConfig.MAILTYPE.驳回入孵申请, reminderMailStr);
// console.log(`入孵申请驳回提醒邮件已发送给企业 ${eId},时间:${new Date().toLocaleString()},环境:${production}`);
// } else {
// console.log(`企业 ${eId} 已重新提交申请或状态已变更,无需发送提醒邮件,时间:${new Date().toLocaleString()}`);
// }
// // 设置下一次检查(无论是否发送邮件)
// setTimeout(scheduleApplicationRejectionReminder, REMINDER_INTERVAL);
// } catch (error) {
// console.error(`检查并发送入孵申请驳回提醒邮件失败:`, error);
// // 即使出错,也尝试设置下一次检查
// setTimeout(scheduleApplicationRejectionReminder, REMINDER_INTERVAL);
// }
// };
// // 辅助函数:检查是否应该继续提醒(针对申请驳回场景)
// const checkShouldContinueForApplicationRejection = async (enterpriseId: string): Promise<boolean> => {
// try {
// // 1. 检查企业是否关闭了邮件提醒
// const enterpriseInfo = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.企业基础信息表,
// { eId: enterpriseId },
// ["emailReminder", "register"]
// );
// if (!enterpriseInfo) {
// console.log(`企业 ${enterpriseId} 信息不存在,停止提醒`);
// return false; // 企业不存在,停止提醒
// }
// if (enterpriseInfo.emailReminder != enumConfig.STATE.是) {
// console.log(`企业 ${enterpriseId} 已关闭邮件提醒,符合终止条件`);
// return false; // 已关闭提醒,停止
// }
// // 2. 检查企业是否已重新提交申请(register不再是已驳回)
// if (enterpriseInfo.register != enumConfig.CHANGESTATE.已驳回) {
// console.log(`企业 ${enterpriseId} 已重新提交申请,符合终止条件`);
// return false; // 已重新提交,停止提醒
// }
// // 3. 检查企业是否已通过入孵申请
// const passCheck = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.入孵申请审批表,
// {
// eId: enterpriseId,
// changeType: enumConfig.CHANGETYPE.入孵申请,
// changeState: enumConfig.CHANGESTATE.已通过
// },
// ["approvalId"]
// );
// if (passCheck && passCheck.approvalId) {
// console.log(`企业 ${enterpriseId} 的入孵申请已通过,停止提醒`);
// return false; // 申请已通过,停止提醒
// }
// // 4. 检查企业是否已通过入孵材料审核
// const materialPassCheck = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.入孵申请审批表,
// {
// eId: enterpriseId,
// changeType: enumConfig.CHANGETYPE.入孵材料审批,
// changeState: enumConfig.CHANGESTATE.已通过
// },
// ["approvalId"]
// );
// if (materialPassCheck && materialPassCheck.approvalId) {
// console.log(`企业 ${enterpriseId} 已通过入孵材料审核,停止提醒`);
// return false; // 已通过材料审核,停止提醒
// }
// // 所有检查通过,继续提醒
// return true;
// } catch (error) {
// console.error(`检查申请驳回终止条件失败,企业ID: ${enterpriseId}`, error);
// return true; // 出错时默认继续
// }
// };
// // 记录提醒设置信息
// console.log(`已为企业 ${eId} 设置周期性入孵申请驳回提醒`, {
// 企业名称: resInfo.enterpriseName,
// 环境模式: production,
// 提醒间隔: `${REMINDER_INTERVAL}ms (${REMINDER_INTERVAL / (60 * 1000)}分钟)`,
// 首次提醒时间: new Date(Date.now() + REMINDER_INTERVAL).toLocaleString()
// });
// // 设置第一次检查
// setTimeout(scheduleApplicationRejectionReminder, REMINDER_INTERVAL);
// }
return
{
isSuccess
:
true
};
}
/**
* 入孵申请驳回
* @param eId
* @param descType 驳回类型 [1, 2]
* @param desc
* @returns
*/
// export async function settleInEnterpriseOut(eId:string, descType, desc:string) {
// let filesList = ["eId", "enterpriseName", "uscc", "logonTime", "state", "emailReminder"];
// let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList);
// if (!resInfo || !resInfo.eId) {
// throw new BizError(ERRORENUM.数据不存在);
// }
// let params = {
// register: enumConfig.CHANGESTATE.已驳回,
// // isNewApplication: enumConfig.STATE.否
// };
// await operationalData( OPERATIONALDATATYPE.修改, TABLENAME.企业基础信息表, params, { eId });
// let descStr = "";
// for(let i = 0; i < descType.length; i++) {
// if (descType[i] == enumConfig.DESCTYPE.其他) {
// if (desc) descStr += `${desc};`
// } else {
// descStr += `${changeEnumValue(enumConfig.DESCTYPE, descType[i])};`;
// }
// }
// let descTypeStr = JSON.stringify(descType) || '[]';
// let addInfo = {
// approvalId: randomId(TABLEID.入孵申请审批表),
// eId,
// changeType: enumConfig.CHANGETYPE.入孵申请,
// changeState: enumConfig.CHANGESTATE.已驳回,
// createTimeMs: getMySqlMs(),
// descType:descTypeStr,
// desc:descStr,
// }
// await operationalData( OPERATIONALDATATYPE.增加, TABLENAME.入孵申请审批表, addInfo, {} );
// /**发送邮件 - 首次驳回通知 */
// let mailStr = "";
// mailStr += "<p>感谢贵公司对【雨艺孵化器】的关注与信任。经我们初步审核,遗憾地通知您,贵公司此次入孵申请<span style='font-weight: 700;'>未通过初审</span>。主要原因为:</p>";
// mailStr += `<ul>`;
// mailStr += `<li>${descStr}</li>`;
// mailStr += `</ul>`;
// mailStr += `<p>以上内容仅作为此次审核意见供参考,您可根据反馈进行优化调整。如后续有相关优化材料或补充说明,欢迎重新提交申请。</p>`;
// mailStr += `<p>我们期待未来与贵公司的合作机会,衷心祝愿贵公司业务发展顺利!</p>`;
// await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵申请, mailStr );
// /**如果emailReminder为是,则设置7天后重复提醒机制 */
// if (resInfo.emailReminder == enumConfig.STATE.是) {
// // 创建驳回申请的周期性提醒函数
// const scheduleRejectionReminder = async () => {
// try {
// // 检查是否应该继续提醒
// const shouldContinue = await checkShouldContinueForRejection(eId);
// if (!shouldContinue) {
// console.log(`为企业 ${eId} 停止周期性入孵申请驳回提醒,时间:${new Date().toLocaleString()}`);
// return; // 终止循环
// }
// // 获取最新的企业状态
// const currentInfo = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.企业基础信息表,
// {eId},
// ["register"]
// );
// // 如果企业仍然是已驳回状态,发送提醒邮件
// if (currentInfo && currentInfo.register === enumConfig.CHANGESTATE.已驳回) {
// let reminderMailStr = "";
// reminderMailStr += "<p>【雨艺孵化器】入孵申请提醒</p>";
// reminderMailStr += "<p>尊敬的客户:</p>";
// reminderMailStr += "<p>我们注意到您之前在" + moment().subtract(7, 'days').format("YYYY-MM-DD") + "提交的入孵申请未通过初审,目前尚未收到您的重新提交。</p>";
// reminderMailStr += `<p>驳回原因:${descStr}</p>`;
// reminderMailStr += "<p>如果您仍有入驻意向,请根据审核意见完善资料后重新提交申请。</p>";
// reminderMailStr += "<p>您可以通过以下方式重新提交:</p>";
// reminderMailStr += "<p><span style='font-weight: 700;'>*电脑端:</span>https://fh.tninnopark.cn/incubatorApply</p>";
// reminderMailStr += "<p><span style='font-weight: 700;'>*手机端:</span>扫描下方二维码:</p>";
// reminderMailStr += "<p><img src='https://fh.tninnopark.cn/yuyi/files/域名访问.png' /></p>";
// reminderMailStr += "<p>如有任何疑问,欢迎随时联系我们。</p>";
// reminderMailStr += "<p>期待您的回复!</p>";
// await systemSendMail(eId, enumConfig.MAILTYPE.驳回入孵申请, reminderMailStr);
// console.log(`入孵申请驳回提醒邮件已发送给企业 ${eId},时间:${new Date().toLocaleString()}`);
// } else {
// console.log(`企业 ${eId} 已重新提交申请或状态已变更,无需发送提醒邮件,时间:${new Date().toLocaleString()}`);
// }
// // 7天后再次检查(无论是否发送邮件)
// setTimeout(scheduleRejectionReminder, 7 * 24 * 60 * 60 * 1000);
// } catch (error) {
// console.error(`检查并发送入孵申请驳回提醒邮件失败:`, error);
// // 即使出错,7天后也重试
// setTimeout(scheduleRejectionReminder, 7 * 24 * 60 * 60 * 1000);
// }
// };
// // 辅助函数:检查是否应该继续提醒(针对驳回场景)
// const checkShouldContinueForRejection = async (enterpriseId: string): Promise<boolean> => {
// try {
// // 1. 检查企业是否关闭了邮件提醒
// const enterpriseInfo = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.企业基础信息表,
// { eId: enterpriseId },
// ["emailReminder", "register"]
// );
// if (!enterpriseInfo) {
// console.log(`企业 ${enterpriseId} 信息不存在,停止提醒`);
// return false; // 企业不存在,停止提醒
// }
// if (enterpriseInfo.emailReminder != enumConfig.STATE.是) {
// console.log(`企业 ${enterpriseId} 已关闭邮件提醒,符合终止条件`);
// return false; // 已关闭提醒,停止
// }
// // 2. 检查企业是否已重新提交申请(register不再是已驳回)
// if (enterpriseInfo.register != enumConfig.CHANGESTATE.已驳回) {
// console.log(`企业 ${enterpriseId} 已重新提交申请,符合终止条件`);
// return false; // 已重新提交,停止提醒
// }
// // 3. 检查企业是否已通过入孵申请
// const passCheck = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.入孵申请审批表,
// {
// eId: enterpriseId,
// changeType: enumConfig.CHANGETYPE.入孵申请,
// changeState: enumConfig.CHANGESTATE.已通过
// },
// ["approvalId"]
// );
// if (passCheck && passCheck.approvalId) {
// console.log(`企业 ${enterpriseId} 的入孵申请已通过,停止提醒`);
// return false; // 申请已通过,停止提醒
// }
// // 4. 检查企业是否已通过入孵材料审核
// const materialPassCheck = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.入孵申请审批表,
// {
// eId: enterpriseId,
// changeType: enumConfig.CHANGETYPE.入孵材料审批,
// changeState: enumConfig.CHANGESTATE.已通过
// },
// ["approvalId"]
// );
// if (materialPassCheck && materialPassCheck.approvalId) {
// console.log(`企业 ${enterpriseId} 已通过入孵材料审核,停止提醒`);
// return false; // 已通过材料审核,停止提醒
// }
// // 所有检查通过,继续提醒
// return true;
// } catch (error) {
// console.error(`检查驳回终止条件失败,企业ID: ${enterpriseId}`, error);
// return true; // 出错时默认继续
// }
// };
// // 7天后开始第一次检查
// setTimeout(scheduleRejectionReminder, 7 * 24 * 60 * 60 * 1000);
// console.log(`已为企业 ${eId} 设置周期性入孵申请驳回提醒,首次检查将在7天后进行`);
// }
// return {isSuccess:true};
// }
/**
* 获取未查看的新入孵申请数量
*/
export
async
function
getNewApplicationCount
()
{
...
...
@@ -500,6 +1243,7 @@ export async function enterpriseRegisterExamineList(enterpriseName, page) {
eId
:
info
.
eId
,
enterpriseName
:
info
.
enterpriseName
,
randomCode
:
info
.
randomCode
,
emailReminder
:
info
.
emailReminder
,
/**跳转用 - 文件链接 */
...
fileDisplayInfo
,
/**显示用 - 文件名称(显示第一个文件) */
...
...
@@ -763,16 +1507,323 @@ export async function enterpriseRegisterExaminePass(eId:string) {
/**
* 修改是否邮件通知状态
* @param eId
* @param emailReminder
*/
export
async
function
updateEmailReminder
(
eId
,
emailReminder
)
{
if
(
!
eId
)
throw
new
BizError
(
ERRORENUM
.
参数错误
);
let
manyTableInfo
:
any
=
{}
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"state"
];
manyTableInfo
[
TABLENAME
.
租赁信息
]
=
{
column
:[
"sanFangXieYi"
,
"fuHuaXieYi"
,
"fangWuZuLing"
,
"fuHuaXieYiBuChong"
,
"chengXinChengNuoHan"
,
"yingYeZhiZhao"
,
"ruFuZiLiao"
,
"ruZhuJiHua"
,
"yaJinZhiFu"
,
"cardCopy"
],
where
:{}
};
let
resInfo
=
await
selectManyTableData
(
OPERATIONALDATATYPE
.
多表单个
,
TABLENAME
.
企业基础信息表
,
{
eId
},
filesList
,
manyTableInfo
);
if
(
!
resInfo
||
!
resInfo
.
eId
)
throw
new
BizError
(
ERRORENUM
.
数据不存在
);
await
operationalData
(
OPERATIONALDATATYPE
.
修改
,
TABLENAME
.
企业基础信息表
,
{
emailReminder
},
{
eId
});
return
{
isSuccess
:
true
};
}
/**
* 入孵材料审核驳回
* @param eId
* @param descType 驳回类型 [1, 2]
* @param desc
* @returns
*/
// export async function enterpriseRegisterExamineOut(eId:string, descType, desc:string) {
// if (!eId) throw new BizError(ERRORENUM.参数错误);
// if (!descType.length) throw new BizError(ERRORENUM.请选择驳回原因);
// let filesList = ["eId", "enterpriseName", "uscc", "logonTime", "state"];
// let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList);
// if (!resInfo || !resInfo.eId) throw new BizError(ERRORENUM.数据不存在);
// let leaseInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.租赁信息, {eId}, []);
// let leaseConf = ["sanFangXieYi", "fuHuaXieYi", "fangWuZuLing", "fuHuaXieYiBuChong", "chengXinChengNuoHan", "yingYeZhiZhao", "ruFuZiLiao", "ruZhuJiHua", "cardCopy"];
// for (let i = 0; i < leaseConf.length; i++) {
// if(!leaseInfo[leaseConf[i]]) {
// throw new BizError(ERRORENUM.该企业暂未提交入孵材料);
// }
// }
// let updateLeaseInfo:any = {yaJinZhiFu:null};
// for (let i = 0; i < leaseConf.length; i++) {
// updateLeaseInfo[leaseConf[i]] = null;
// }
// await operationalData(OPERATIONALDATATYPE.修改, TABLENAME.租赁信息, updateLeaseInfo, {eId});
// await operationalData(OPERATIONALDATATYPE.修改, TABLENAME.企业基础信息表, {state:enumConfig.CHANGESTATE.已驳回, isNewApplication: enumConfig.STATE.是}, {eId});
// let descStr = "";
// for(let i = 0; i < descType.length; i++) {
// if (descType[i] == enumConfig.FILEDESCTYPE.其他) {
// if (desc) descStr += `${desc};`
// } else {
// descStr += `${changeEnumValue(enumConfig.FILEDESCTYPE, descType[i])};`;
// }
// }
// let descTypeStr = JSON.stringify(descType) || '[]';
// let addInfo = {
// approvalId: randomId(TABLEID.入孵申请审批表),
// eId,
// changeType: enumConfig.CHANGETYPE.入孵材料审批,
// changeState: enumConfig.CHANGESTATE.已驳回,
// createTimeMs: getMySqlMs(),
// descType:descTypeStr,
// desc:descStr,
// }
// await operationalData( OPERATIONALDATATYPE.增加, TABLENAME.入孵申请审批表, addInfo, {} );
// /**发送邮件 - 首次驳回通知 */
// let mailStr = "";
// mailStr += "<p>感谢贵公司积极配合入孵流程。经审核,贵公司提交的入孵材料<span style='font-weight: 700;'>暂未通过审核</span>,主要原因如下:</p>";
// mailStr += `<ul>`;
// mailStr += `<li>${descStr}</li>`;
// mailStr += `</ul>`;
// mailStr += `<p>如贵司愿意继续推进入孵流程,可根据上述意见进行材料完善并重新提交。</p>`;
// mailStr += `<p>我们期待贵公司尽快完善材料,并欢迎继续申请入驻。</p>`;
// mailStr += `<p>感谢理解与配合!</p>`;
// await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵材料申请, mailStr );
// /**设置7天后再次提醒 */
// setTimeout(async () => {
// try {
// // 检查企业状态是否仍然是已驳回(未重新提交材料)
// let currentInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, ["state"]);
// if (currentInfo && currentInfo.state === enumConfig.CHANGESTATE.已驳回) {
// let reminderMailStr = "";
// reminderMailStr += "<p>【雨艺孵化器】入孵材料审核提醒</p>";
// reminderMailStr += "<p>尊敬的客户:</p>";
// reminderMailStr += "<p>我们注意到您在7天前提交的入孵材料未通过审核,目前尚未收到您重新提交的完善材料。</p>";
// reminderMailStr += `<p>驳回原因:${descStr}</p>`;
// reminderMailStr += "<p>请您根据审核意见尽快完善相关材料并重新提交,以便我们继续为您处理入孵申请。</p>";
// reminderMailStr += "<p>如有任何疑问,欢迎随时联系我们。</p>";
// reminderMailStr += "<p>期待您的完善材料!</p>";
// await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵材料申请, reminderMailStr);
// console.log(`7天后入孵材料驳回提醒邮件已发送给企业 ${resInfo.eId}`);
// }
// } catch (error) {
// console.error(`发送7天后入孵材料驳回提醒邮件失败:`, error);
// }
// }, 7 * 24 * 60 * 60 * 1000); // 7天后的毫秒数
// return {isSuccess:true};
// }
/**
* 入孵材料审核驳回
* @param eId
* @param descType 驳回类型 [1, 2]
* @param desc
* @returns
*/
export
async
function
enterpriseRegisterExamineOut
(
eId
:
string
,
descType
,
desc
:
string
)
{
// export async function enterpriseRegisterExamineOut(eId:string, descType, desc:string) {
// if (!eId) throw new BizError(ERRORENUM.参数错误);
// if (!descType.length) throw new BizError(ERRORENUM.请选择驳回原因);
// // 添加emailReminder字段查询
// let filesList = ["eId", "enterpriseName", "uscc", "logonTime", "state", "emailReminder"];
// let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList);
// if (!resInfo || !resInfo.eId) throw new BizError(ERRORENUM.数据不存在);
// let leaseInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.租赁信息, {eId}, []);
// let leaseConf = ["sanFangXieYi", "fuHuaXieYi", "fangWuZuLing", "fuHuaXieYiBuChong", "chengXinChengNuoHan", "yingYeZhiZhao", "ruFuZiLiao", "ruZhuJiHua", "cardCopy"];
// for (let i = 0; i < leaseConf.length; i++) {
// if(!leaseInfo[leaseConf[i]]) {
// throw new BizError(ERRORENUM.该企业暂未提交入孵材料);
// }
// }
// let updateLeaseInfo:any = {yaJinZhiFu:null};
// for (let i = 0; i < leaseConf.length; i++) {
// updateLeaseInfo[leaseConf[i]] = null;
// }
// await operationalData(OPERATIONALDATATYPE.修改, TABLENAME.租赁信息, updateLeaseInfo, {eId});
// await operationalData(OPERATIONALDATATYPE.修改, TABLENAME.企业基础信息表, {state:enumConfig.CHANGESTATE.已驳回, isNewApplication: enumConfig.STATE.是}, {eId});
// let descStr = "";
// for(let i = 0; i < descType.length; i++) {
// if (descType[i] == enumConfig.FILEDESCTYPE.其他) {
// if (desc) descStr += `${desc};`
// } else {
// descStr += `${changeEnumValue(enumConfig.FILEDESCTYPE, descType[i])};`;
// }
// }
// let descTypeStr = JSON.stringify(descType) || '[]';
// let addInfo = {
// approvalId: randomId(TABLEID.入孵申请审批表),
// eId,
// changeType: enumConfig.CHANGETYPE.入孵材料审批,
// changeState: enumConfig.CHANGESTATE.已驳回,
// createTimeMs: getMySqlMs(),
// descType:descTypeStr,
// desc:descStr,
// }
// await operationalData( OPERATIONALDATATYPE.增加, TABLENAME.入孵申请审批表, addInfo, {} );
// /**发送邮件 - 首次驳回通知 */
// let mailStr = "";
// mailStr += "<p>感谢贵公司积极配合入孵流程。经审核,贵公司提交的入孵材料<span style='font-weight: 700;'>暂未通过审核</span>,主要原因如下:</p>";
// mailStr += `<ul>`;
// mailStr += `<li>${descStr}</li>`;
// mailStr += `</ul>`;
// mailStr += `<p>如贵司愿意继续推进入孵流程,可根据上述意见进行材料完善并重新提交。</p>`;
// mailStr += `<p>我们期待贵公司尽快完善材料,并欢迎继续申请入驻。</p>`;
// mailStr += `<p>感谢理解与配合!</p>`;
// await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵材料申请, mailStr );
// /**如果emailReminder为是,则设置7天后重复提醒机制 */
// if (resInfo.emailReminder == enumConfig.STATE.是) {
// // 创建材料驳回的周期性提醒函数
// const scheduleMaterialRejectionReminder = async () => {
// try {
// // 检查是否应该继续提醒
// const shouldContinue = await checkShouldContinueForMaterialRejection(eId);
// if (!shouldContinue) {
// console.log(`为企业 ${eId} 停止周期性入孵材料驳回提醒,时间:${new Date().toLocaleString()}`);
// return; // 终止循环
// }
// // 获取最新的企业状态
// const currentInfo = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.企业基础信息表,
// {eId},
// ["state"]
// );
// // 如果企业状态仍然是已驳回(材料未重新提交),发送提醒邮件
// if (currentInfo && currentInfo.state === enumConfig.CHANGESTATE.已驳回) {
// let reminderMailStr = "";
// reminderMailStr += "<p>【雨艺孵化器】入孵材料审核提醒</p>";
// reminderMailStr += "<p>尊敬的客户:</p>";
// reminderMailStr += `<p>我们注意到您之前在${moment().subtract(7, 'days').format("YYYY-MM-DD")}提交的入孵材料未通过审核,目前尚未收到您重新提交的完善材料。</p>`;
// reminderMailStr += `<p>驳回原因:${descStr}</p>`;
// reminderMailStr += "<p>请您根据审核意见尽快完善相关材料并重新提交,以便我们继续为您处理入孵申请。</p>";
// reminderMailStr += "<p>您可以通过以下方式重新提交材料:</p>";
// reminderMailStr += "<p><span style='font-weight: 700;'>*电脑端:</span>https://fh.tninnopark.cn/incubatorApply</p>";
// reminderMailStr += "<p><span style='font-weight: 700;'>*手机端:</span>扫描下方二维码:</p>";
// reminderMailStr += "<p><img src='https://fh.tninnopark.cn/yuyi/files/域名访问.png' /></p>";
// reminderMailStr += "<p>如有任何疑问,欢迎随时联系我们。</p>";
// reminderMailStr += "<p>期待您的完善材料!</p>";
// await systemSendMail(eId, enumConfig.MAILTYPE.驳回入孵材料申请, reminderMailStr);
// console.log(`入孵材料驳回提醒邮件已发送给企业 ${eId},时间:${new Date().toLocaleString()}`);
// } else {
// console.log(`企业 ${eId} 已重新提交材料或状态已变更,无需发送提醒邮件,时间:${new Date().toLocaleString()}`);
// }
// // 7天后再次检查(无论是否发送邮件)
// setTimeout(scheduleMaterialRejectionReminder, 7 * 24 * 60 * 60 * 1000);
// } catch (error) {
// console.error(`检查并发送入孵材料驳回提醒邮件失败:`, error);
// // 即使出错,7天后也重试
// setTimeout(scheduleMaterialRejectionReminder, 7 * 24 * 60 * 60 * 1000);
// }
// };
// // 辅助函数:检查是否应该继续提醒(针对材料驳回场景)
// const checkShouldContinueForMaterialRejection = async (enterpriseId: string): Promise<boolean> => {
// try {
// // 1. 检查企业是否关闭了邮件提醒
// const enterpriseInfo = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.企业基础信息表,
// { eId: enterpriseId },
// ["emailReminder", "state"]
// );
// if (!enterpriseInfo) {
// console.log(`企业 ${enterpriseId} 信息不存在,停止提醒`);
// return false; // 企业不存在,停止提醒
// }
// if (enterpriseInfo.emailReminder != enumConfig.STATE.是) {
// console.log(`企业 ${enterpriseId} 已关闭邮件提醒,符合终止条件`);
// return false; // 已关闭提醒,停止
// }
// // 2. 检查企业状态是否不再是"已驳回"
// if (enterpriseInfo.state != enumConfig.CHANGESTATE.已驳回) {
// console.log(`企业 ${enterpriseId} 状态已变更,符合终止条件`);
// return false; // 状态已变更(可能已重新提交或通过),停止提醒
// }
// // 3. 检查企业是否已通过入孵材料审核
// const materialPassCheck = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.入孵申请审批表,
// {
// eId: enterpriseId,
// changeType: enumConfig.CHANGETYPE.入孵材料审批,
// changeState: enumConfig.CHANGESTATE.已通过
// },
// ["approvalId"]
// );
// if (materialPassCheck && materialPassCheck.approvalId) {
// console.log(`企业 ${enterpriseId} 已通过入孵材料审核,停止提醒`);
// return false; // 已通过材料审核,停止提醒
// }
// // 4. 检查企业是否有新的入孵材料提交记录(即使还未审核通过)
// const newMaterialSubmission = await selectData(
// OPERATIONALDATATYPE.查询单个,
// TABLENAME.租赁信息,
// { eId: enterpriseId },
// ["sanFangXieYi", "fuHuaXieYi"] // 检查任意文件字段
// );
// // 如果有任一材料字段不为空,说明已重新提交
// if (newMaterialSubmission &&
// (newMaterialSubmission.sanFangXieYi || newMaterialSubmission.fuHuaXieYi)) {
// console.log(`企业 ${enterpriseId} 已重新提交材料,停止提醒`);
// return false; // 已重新提交材料,停止提醒
// }
// // 所有检查通过,继续提醒
// return true;
// } catch (error) {
// console.error(`检查材料驳回终止条件失败,企业ID: ${enterpriseId}`, error);
// return true; // 出错时默认继续
// }
// };
// // 7天后开始第一次检查
// setTimeout(scheduleMaterialRejectionReminder, 7 * 24 * 60 * 60 * 1000);
// console.log(`已为企业 ${eId} 设置周期性入孵材料驳回提醒,首次检查将在7天后进行`);
// }
// return {isSuccess:true};
// }
/**
* 入孵材料审核驳回
* @param eId 企业ID
* @param descType 驳回类型 [1, 2]
* @param desc 驳回原因
* @param production 环境标识:"production"表示生产环境,其他表示测试环境
* @returns
*/
export
async
function
enterpriseRegisterExamineOut
(
eId
:
string
,
descType
,
desc
:
string
,
production
:
string
=
"test"
)
{
if
(
!
eId
)
throw
new
BizError
(
ERRORENUM
.
参数错误
);
if
(
!
descType
.
length
)
throw
new
BizError
(
ERRORENUM
.
请选择驳回原因
);
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"state"
];
// 添加emailReminder字段查询
let
filesList
=
[
"eId"
,
"enterpriseName"
,
"uscc"
,
"logonTime"
,
"state"
,
"emailReminder"
];
let
resInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业基础信息表
,
{
eId
},
filesList
);
if
(
!
resInfo
||
!
resInfo
.
eId
)
throw
new
BizError
(
ERRORENUM
.
数据不存在
);
...
...
@@ -825,33 +1876,150 @@ export async function enterpriseRegisterExamineOut(eId:string, descType, desc:st
mailStr
+=
`<p>感谢理解与配合!</p>`
;
await
systemSendMail
(
resInfo
.
eId
,
enumConfig
.
MAILTYPE
.
驳回入孵材料申请
,
mailStr
);
/**设置7天后再次提醒 */
setTimeout
(
async
()
=>
{
/**如果emailReminder为是,则设置周期性提醒机制 */
if
(
resInfo
.
emailReminder
==
enumConfig
.
STATE
.
是
)
{
// 根据参数确定提醒间隔
const
REMINDER_INTERVAL
=
production
===
"production"
?
7
*
24
*
60
*
60
*
1000
// 生产环境:7天
:
60
*
1000
;
// 测试环境:1分钟
// 创建材料驳回的周期性提醒函数
const
scheduleMaterialRejectionReminder
=
async
()
=>
{
try
{
// 检查企业状态是否仍然是已驳回(未重新提交材料)
let
currentInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业基础信息表
,
{
eId
},
[
"state"
]);
// 检查是否应该继续提醒
const
shouldContinue
=
await
checkShouldContinueForMaterialRejection
(
eId
);
if
(
!
shouldContinue
)
{
console
.
log
(
`为企业
${
eId
}
停止周期性入孵材料驳回提醒,时间:
${
new
Date
().
toLocaleString
()}
`
);
return
;
// 终止循环
}
// 获取最新的企业状态
const
currentInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业基础信息表
,
{
eId
},
[
"state"
]
);
// 如果企业状态仍然是已驳回(材料未重新提交),发送提醒邮件
if
(
currentInfo
&&
currentInfo
.
state
===
enumConfig
.
CHANGESTATE
.
已驳回
)
{
let
reminderMailStr
=
""
;
reminderMailStr
+=
"<p>【雨艺孵化器】入孵材料审核提醒</p>"
;
reminderMailStr
+=
"<p>尊敬的客户:</p>"
;
reminderMailStr
+=
"<p>我们注意到您在7天前提交的入孵材料未通过审核,目前尚未收到您重新提交的完善材料。</p>"
;
reminderMailStr
+=
`<p>我们注意到您之前在
${
moment
().
subtract
(
REMINDER_INTERVAL
/
(
24
*
60
*
60
*
1000
),
'days'
).
format
(
"YYYY-MM-DD"
)}
提交的入孵材料未通过审核,目前尚未收到您重新提交的完善材料。</p>`
;
reminderMailStr
+=
`<p>驳回原因:
${
descStr
}
</p>`
;
reminderMailStr
+=
"<p>请您根据审核意见尽快完善相关材料并重新提交,以便我们继续为您处理入孵申请。</p>"
;
reminderMailStr
+=
"<p>您可以通过以下方式重新提交材料:</p>"
;
reminderMailStr
+=
"<p><span style='font-weight: 700;'>*电脑端:</span>https://fh.tninnopark.cn/incubatorApply</p>"
;
reminderMailStr
+=
"<p><span style='font-weight: 700;'>*手机端:</span>扫描下方二维码:</p>"
;
reminderMailStr
+=
"<p><img src='https://fh.tninnopark.cn/yuyi/files/域名访问.png' /></p>"
;
reminderMailStr
+=
"<p>如有任何疑问,欢迎随时联系我们。</p>"
;
reminderMailStr
+=
"<p>期待您的完善材料!</p>"
;
await
systemSendMail
(
resInfo
.
eId
,
enumConfig
.
MAILTYPE
.
驳回入孵材料申请
,
reminderMailStr
);
console
.
log
(
`7天后入孵材料驳回提醒邮件已发送给企业
${
resInfo
.
eId
}
`
);
await
systemSendMail
(
eId
,
enumConfig
.
MAILTYPE
.
驳回入孵材料申请
,
reminderMailStr
);
console
.
log
(
`入孵材料驳回提醒邮件已发送给企业
${
eId
}
,时间:
${
new
Date
().
toLocaleString
()}
,环境:
${
production
}
`
);
}
else
{
console
.
log
(
`企业
${
eId
}
已重新提交材料或状态已变更,无需发送提醒邮件,时间:
${
new
Date
().
toLocaleString
()}
`
);
}
// 设置下一次检查(无论是否发送邮件)
setTimeout
(
scheduleMaterialRejectionReminder
,
REMINDER_INTERVAL
);
}
catch
(
error
)
{
console
.
error
(
`检查并发送入孵材料驳回提醒邮件失败:`
,
error
);
// 即使出错,也尝试设置下一次检查
setTimeout
(
scheduleMaterialRejectionReminder
,
REMINDER_INTERVAL
);
}
};
// 辅助函数:检查是否应该继续提醒(针对材料驳回场景)
const
checkShouldContinueForMaterialRejection
=
async
(
enterpriseId
:
string
):
Promise
<
boolean
>
=>
{
try
{
// 1. 检查企业是否关闭了邮件提醒
const
enterpriseInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业基础信息表
,
{
eId
:
enterpriseId
},
[
"emailReminder"
,
"state"
]
);
if
(
!
enterpriseInfo
)
{
console
.
log
(
`企业
${
enterpriseId
}
信息不存在,停止提醒`
);
return
false
;
// 企业不存在,停止提醒
}
if
(
enterpriseInfo
.
emailReminder
!=
enumConfig
.
STATE
.
是
)
{
console
.
log
(
`企业
${
enterpriseId
}
已关闭邮件提醒,符合终止条件`
);
return
false
;
// 已关闭提醒,停止
}
// 2. 检查企业状态是否不再是"已驳回"
if
(
enterpriseInfo
.
state
!=
enumConfig
.
CHANGESTATE
.
已驳回
)
{
console
.
log
(
`企业
${
enterpriseId
}
状态已变更,符合终止条件`
);
return
false
;
// 状态已变更(可能已重新提交或通过),停止提醒
}
// 3. 检查企业是否已通过入孵材料审核
const
materialPassCheck
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
入孵申请审批表
,
{
eId
:
enterpriseId
,
changeType
:
enumConfig
.
CHANGETYPE
.
入孵材料审批
,
changeState
:
enumConfig
.
CHANGESTATE
.
已通过
},
[
"approvalId"
]
);
if
(
materialPassCheck
&&
materialPassCheck
.
approvalId
)
{
console
.
log
(
`企业
${
enterpriseId
}
已通过入孵材料审核,停止提醒`
);
return
false
;
// 已通过材料审核,停止提醒
}
// 4. 检查企业是否有新的入孵材料提交记录(即使还未审核通过)
const
newMaterialSubmission
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
租赁信息
,
{
eId
:
enterpriseId
},
[
"sanFangXieYi"
,
"fuHuaXieYi"
]
// 检查任意文件字段
);
// 如果有任一材料字段不为空,说明已重新提交
if
(
newMaterialSubmission
&&
(
newMaterialSubmission
.
sanFangXieYi
||
newMaterialSubmission
.
fuHuaXieYi
))
{
console
.
log
(
`企业
${
enterpriseId
}
已重新提交材料,停止提醒`
);
return
false
;
// 已重新提交材料,停止提醒
}
// 所有检查通过,继续提醒
return
true
;
}
catch
(
error
)
{
console
.
error
(
`发送7天后入孵材料驳回提醒邮件失败:`
,
error
);
console
.
error
(
`检查材料驳回终止条件失败,企业ID:
${
enterpriseId
}
`
,
error
);
return
true
;
// 出错时默认继续
}
};
// 记录提醒设置信息
console
.
log
(
`已为企业
${
eId
}
设置周期性入孵材料驳回提醒`
,
{
企业名称
:
resInfo
.
enterpriseName
,
环境模式
:
production
,
提醒间隔
:
`
${
REMINDER_INTERVAL
}
ms (
${
REMINDER_INTERVAL
/
(
60
*
1000
)}
分钟)`
,
首次提醒时间
:
new
Date
(
Date
.
now
()
+
REMINDER_INTERVAL
).
toLocaleString
()
});
// 设置第一次检查
setTimeout
(
scheduleMaterialRejectionReminder
,
REMINDER_INTERVAL
);
}
},
7
*
24
*
60
*
60
*
1000
);
// 7天后的毫秒数
return
{
isSuccess
:
true
};
}
/**
* 编辑入孵材料
* @param eId
...
...
src/biz/zaiFu.ts
View file @
936cbd63
...
...
@@ -3,14 +3,14 @@
*/
import
moment
=
require
(
"moment"
);
import
{
OPERATIONALDATATYPE
,
TABLENAME
}
from
"../config/enum/dbEnum"
;
import
{
OPERATIONALDATATYPE
,
TABLE
ID
,
TABLE
NAME
}
from
"../config/enum/dbEnum"
;
import
{
operationalData
,
paginateArray
,
selectData
,
selectManyTableData
}
from
"../data/operationalData"
;
import
{
changeAdd
}
from
"../util/piecemeal"
;
import
{
changeEnumManyValue
,
changeEnumValue
}
from
"../util/verificationEnum"
;
import
*
as
enumConfig
from
"../config/enum/enum"
;
import
{
BizError
}
from
"../util/bizError"
;
import
{
ERRORENUM
}
from
"../config/enum/errorEnum"
;
import
{
getMySqlMs
,
getPwdMd5
}
from
"../tools/system"
;
import
{
getMySqlMs
,
getPwdMd5
,
randomId
}
from
"../tools/system"
;
import
{
BUILDING
}
from
"../config/enum/enum"
;
...
...
@@ -234,6 +234,77 @@ export async function enterpriseMigrateList(enterpriseName:string, page:number)
/**
* 移除迁出状态,返回在孵企业
* @param eId 企业ID
* @returns
*/
export
async
function
enterpriseReturnToIncubation
(
eId
:
string
)
{
// 1. 验证企业是否存在且处于迁出状态
let
filesList
=
[
"eId"
,
"state"
,
"startTime"
,
"endTime"
];
let
resInfo
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
企业孵化信息
,
{
eId
},
filesList
);
if
(
!
resInfo
||
!
resInfo
.
eId
)
{
throw
new
BizError
(
ERRORENUM
.
数据不存在
);
}
// 检查企业当前状态是否为迁出
if
(
resInfo
.
state
!==
enumConfig
.
FUHUASTATE
.
迁出
)
{
throw
new
BizError
(
ERRORENUM
.
该企业当前不在迁出状态
);
}
// 2. 更新企业孵化信息为在孵状态
let
updateInfo
=
{
state
:
enumConfig
.
FUHUASTATE
.
实体孵化
,
// 返回实体孵化状态
moveOutTime
:
null
,
// 清空迁出时间
moveOutType
:
null
,
// 清空迁出类型
moveOutTrace
:
null
,
// 清空迁出去向
returnTime
:
getMySqlMs
()
// 记录返回时间
};
await
operationalData
(
OPERATIONALDATATYPE
.
修改
,
TABLENAME
.
企业孵化信息
,
updateInfo
,
{
eId
});
// 3. 同步创建返回记录到审批表
let
addApprovalInfo
=
{
approvalId
:
randomId
(
TABLEID
.
入孵申请审批表
),
eId
,
changeType
:
enumConfig
.
CHANGETYPE
.
返回在孵
,
// 需要添加这个枚举值
changeState
:
enumConfig
.
CHANGESTATE
.
已通过
,
createTimeMs
:
getMySqlMs
(),
desc
:
"企业从迁出状态返回在孵"
};
await
operationalData
(
OPERATIONALDATATYPE
.
增加
,
TABLENAME
.
入孵申请审批表
,
addApprovalInfo
,
{});
// 4. 同步更新在孵企业面积
/**在孵企业 当前时间小于孵化结束时间 */
let
在孵面积
=
0
;
let
araeParam
=
{
column
:[
"area"
,
"unitPrice"
,
"roomNumber"
,
"rent"
],
where
:{}
};
let
zaifuTableInfo
:
any
=
{};
zaifuTableInfo
[
TABLENAME
.
租赁信息
]
=
araeParam
;
zaifuTableInfo
[
TABLENAME
.
企业孵化信息
]
=
{
column
:[
"state"
,
"startTime"
,
"endTime"
],
where
:{
state
:{
"%ne%"
:
enumConfig
.
FUHUASTATE
.
迁出
}}
};
let
zaifuResList
=
await
selectManyTableData
(
OPERATIONALDATATYPE
.
多表联查
,
TABLENAME
.
企业基础信息表
,
{
state
:
enumConfig
.
CHANGESTATE
.
已通过
},
[
"eId"
],
zaifuTableInfo
);
zaifuResList
.
forEach
(
info
=>
{
info
.
enterprise_leases
.
forEach
(
lease
=>
{
在孵面积
+=
parseFloat
(
lease
.
area
);
})
})
let
yuyiList
=
await
selectData
(
OPERATIONALDATATYPE
.
查询单个
,
TABLENAME
.
羽翼孵化器信息
,
{},
[]);
if
(
在孵面积
!=
yuyiList
.
zaifuArea
)
await
operationalData
(
OPERATIONALDATATYPE
.
修改
,
TABLENAME
.
羽翼孵化器信息
,
{
zaifuArea
:
在孵面积
},
{
yId
:
yuyiList
.
yId
});
console
.
log
(
`企业
${
eId
}
已成功从迁出状态返回在孵`
);
return
{
isSuccess
:
true
,
message
:
"企业已成功返回在孵状态"
};
}
/**
* 重置密码
* @param eId
*/
...
...
src/config/enum/enum.ts
View file @
936cbd63
...
...
@@ -288,7 +288,8 @@ export enum CHANGESTATE {
*/
export
enum
CHANGETYPE
{
入孵申请
=
1
,
入孵材料审批
=
2
入孵材料审批
=
2
,
返回在孵
=
3
,
}
...
...
src/config/enum/errorEnum.ts
View file @
936cbd63
...
...
@@ -44,7 +44,8 @@ export enum ERRORENUM {
请选择驳回原因
,
原密码错误
,
密码不一致
,
系统错误
系统错误
,
该企业当前不在迁出状态
}
export
enum
ERRORCODEENUM
{
...
...
src/main.ts
View file @
936cbd63
...
...
@@ -14,7 +14,7 @@ async function lanuch() {
httpServer
.
createServer
(
systemConfig
.
port
);
console
.
log
(
'This indicates that the server is started successfully.'
);
//
await initApiDataStorage();
await
initApiDataStorage
();
// console.log("更新加密后密码格式...");
// await migrateEnterpriseUserPasswords();
...
...
src/routers/admin.ts
View file @
936cbd63
...
...
@@ -35,6 +35,7 @@ export function setRouter(httpServer) {
httpServer
.
post
(
'/admin/enterprise/settlein/examine/list'
,
checkUser
,
asyncHandler
(
examineSettleIn
));
httpServer
.
post
(
'/admin/enterprise/settlein/examine/pass'
,
checkUser
,
asyncHandler
(
examineSettleInPass
));
//入孵材料审核 通过
httpServer
.
post
(
'/admin/enterprise/settlein/examine/out'
,
checkUser
,
asyncHandler
(
examineSettleInOut
));
//驳回
httpServer
.
post
(
'/admin/enterprise/settlein/examine/emailreminder'
,
checkUser
,
asyncHandler
(
updateEmailReminder
));
// //通知
httpServer
.
post
(
'/admin/notice/list'
,
checkUser
,
asyncHandler
(
noticeList
));
...
...
@@ -53,6 +54,7 @@ export function setRouter(httpServer) {
httpServer
.
post
(
'/admin/library/enterprise/list'
,
checkUser
,
asyncHandler
(
enterpriseList
));
httpServer
.
post
(
'/admin/library/enterprise/migrate/out'
,
checkUser
,
asyncHandler
(
enterpriseMigrateOut
));
//在孵企业迁出功能
httpServer
.
post
(
'/admin/library/enterprise/migrate/list'
,
checkUser
,
asyncHandler
(
enterpriseMigrateList
));
//迁出企业列表
httpServer
.
post
(
'/admin/library/enterprise/toincubation'
,
checkUser
,
asyncHandler
(
enterpriseReturnToIncubation
));
//二期新增-移除迁出状态,返回在孵企业
httpServer
.
post
(
'/admin/library/enterprise/details'
,
checkUser
,
asyncHandler
(
enterpriseDetails
));
httpServer
.
post
(
'/admin/library/enterprise/resetpwd'
,
checkUser
,
asyncHandler
(
resetPwd
));
// httpServer.post('/admin/library/enterprise/details', checkUser, asyncHandler(enterpriseById));
...
...
@@ -393,6 +395,21 @@ async function enterpriseMigrateList(req, res) {
res
.
success
(
result
);
}
/**
* 移除迁出状态,返回在孵企业
* @param req
* @param res
*/
async
function
enterpriseReturnToIncubation
(
req
,
res
)
{
const
UserInfo
=
req
.
userInfo
;
let
{
eId
}
=
req
.
body
;
let
result
=
await
zaiFuBiz
.
enterpriseReturnToIncubation
(
eId
);
res
.
success
(
result
);
}
/**
* 在孵企业详情
* @param req
...
...
@@ -820,20 +837,20 @@ async function settleIn(req, res) {
/**
*
*
入孵申请通过
* @param req
* @param res
*/
async
function
settleInPass
(
req
,
res
)
{
const
UserInfo
=
req
.
userInfo
;
let
{
eId
}
=
req
.
body
let
result
=
await
ruFuBiz
.
settleInEnterprisePass
(
eId
);
let
result
=
await
ruFuBiz
.
settleInEnterprisePass
(
eId
,
"production"
);
res
.
success
(
result
);
}
/**
*
*
入孵申请回显
* @param req
* @param res
*/
...
...
@@ -847,7 +864,7 @@ async function settleInById(req, res) {
/**
*
*
入孵申请驳回
* @param req
* @param res
*/
...
...
@@ -966,8 +983,20 @@ async function examineSettleInPass(req, res) {
async
function
examineSettleInOut
(
req
,
res
)
{
const
UserInfo
=
req
.
userInfo
;
let
{
eId
,
descType
,
desc
}
=
req
.
body
;
let
result
=
await
ruFuBiz
.
enterpriseRegisterExamineOut
(
eId
,
descType
,
desc
);
let
result
=
await
ruFuBiz
.
enterpriseRegisterExamineOut
(
eId
,
descType
,
desc
,
"production"
);
res
.
success
(
result
);
}
/**
* 修改是否邮件通知状态
* @param req
* @param res
*/
async
function
updateEmailReminder
(
req
,
res
)
{
let
{
eId
,
emailReminder
}
=
req
.
body
;
let
result
=
await
ruFuBiz
.
updateEmailReminder
(
eId
,
emailReminder
);
res
.
success
(
result
);
}
...
...
src/routers/ledger.ts
View file @
936cbd63
...
...
@@ -23,8 +23,8 @@ export function setRouter(httpServer) {
*/
async
function
ledgerList
(
req
,
res
)
{
const
UserInfo
=
req
.
userInfo
;
let
{
enterpriseName
,
logonStartTime
,
logonEndTime
,
building
,
page
}
=
req
.
body
let
result
=
await
ledgerBiz
.
ledgerList
(
enterpriseName
,
logonStartTime
,
logonEndTime
,
building
,
page
);
let
{
enterpriseName
,
phone
,
logonStartTime
,
logonEndTime
,
building
,
page
}
=
req
.
body
let
result
=
await
ledgerBiz
.
ledgerList
(
enterpriseName
,
phone
,
logonStartTime
,
logonEndTime
,
building
,
page
);
res
.
success
(
result
);
}
...
...
src/routers/userRuFu.ts
View file @
936cbd63
...
...
@@ -13,7 +13,6 @@ export function setRouter(httpServer) {
httpServer
.
post
(
'/admin/enterprise/rufu/settleininfo'
,
asyncHandler
(
settleInById
));
httpServer
.
post
(
'/admin/enterprise/rufu/info'
,
asyncHandler
(
getRuFu
));
httpServer
.
post
(
'/admin/enterprise/rufu/update'
,
asyncHandler
(
updateRuFu
));
}
...
...
@@ -23,7 +22,7 @@ export function setRouter(httpServer) {
* @param res
*/
async
function
register
(
req
,
res
)
{
let
{
userName
,
phone
,
pwd
}
=
req
.
body
let
{
userName
,
phone
,
pwd
}
=
req
.
body
let
result
=
await
userRuFuBiz
.
enterpriseRegister
(
userName
,
phone
,
pwd
);
res
.
success
(
result
);
}
...
...
@@ -35,20 +34,19 @@ export function setRouter(httpServer) {
* @param res
*/
async
function
login
(
req
,
res
)
{
let
{
phone
,
pwd
}
=
req
.
body
let
{
phone
,
pwd
}
=
req
.
body
let
result
=
await
userRuFuBiz
.
enterpriseLogin
(
phone
,
pwd
);
res
.
success
(
result
);
}
/**
* 获取入孵流程状态
* @param req
* @param res
*/
async
function
ruFuState
(
req
,
res
)
{
let
{
uId
}
=
req
.
body
let
{
uId
}
=
req
.
body
let
result
=
await
userRuFuBiz
.
getRuFuState
(
uId
);
res
.
success
(
result
);
}
...
...
@@ -66,8 +64,9 @@ export function setRouter(httpServer) {
res
.
success
(
result
);
}
/**
*
*
入孵申请回显
* @param req
* @param res
*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment