Commit 936cbd63 by chenjinjing

no message

parent 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();
});
}
...@@ -130,7 +130,7 @@ import { AdminRegisterUpdateConfig } from "../config/eccParam/enterprise"; ...@@ -130,7 +130,7 @@ import { AdminRegisterUpdateConfig } from "../config/eccParam/enterprise";
* @param page * @param page
* @returns {dataList, dataCount} 数据列表, 数据总数 * @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.已通过}; let selectParam: any = {state: enumConfig.CHANGESTATE.已通过};
if (enterpriseName) { if (enterpriseName) {
selectParam.enterpriseName = { "%like%": enterpriseName }; selectParam.enterpriseName = { "%like%": enterpriseName };
...@@ -139,11 +139,17 @@ export async function ledgerList(enterpriseName:string, logonStartTime:Number, l ...@@ -139,11 +139,17 @@ export async function ledgerList(enterpriseName:string, logonStartTime:Number, l
selectParam.logonTime = {"%between%":[getMySqlMs(logonStartTime), getMySqlMs(logonEndTime)]} 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 filesList = ["eId", "enterpriseName", "uscc", "logonTime", "logonAddress", "qiYeGuiMo"];
let manyTableInfo: any = {}; let manyTableInfo: any = {};
let rufuSelectParam = { state: { "%between%": [enumConfig.FUHUASTATE.实体孵化, enumConfig.FUHUASTATE.虚拟孵化] } }; let rufuSelectParam = { state: { "%between%": [enumConfig.FUHUASTATE.实体孵化, enumConfig.FUHUASTATE.虚拟孵化] } };
manyTableInfo[TABLENAME.企业孵化信息] = { column:["moveOutTime", "moveOutType", "startTime", "endTime"], where: rufuSelectParam}; 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 ); let resInfo = await selectManyTableData( OPERATIONALDATATYPE.多表联查, TABLENAME.企业基础信息表, selectParam, filesList, manyTableInfo );
/**查询租赁表信息 */ /**查询租赁表信息 */
...@@ -260,6 +266,7 @@ export async function ledgerList(enterpriseName:string, logonStartTime:Number, l ...@@ -260,6 +266,7 @@ export async function ledgerList(enterpriseName:string, logonStartTime:Number, l
logonAddress, logonAddress,
qiYeGuiMo, qiYeGuiMo,
enterprise_fuhuas, enterprise_fuhuas,
enterprise_users,
} = info; } = info;
// 过滤条件:如果没有租赁信息,跳过 // 过滤条件:如果没有租赁信息,跳过
...@@ -288,10 +295,17 @@ export async function ledgerList(enterpriseName:string, logonStartTime:Number, l ...@@ -288,10 +295,17 @@ export async function ledgerList(enterpriseName:string, logonStartTime:Number, l
知识产权总数: 0 知识产权总数: 0
}; };
// 获取企业登录信息
let phone = "-";
if (enterprise_users[0]?.phone) {
phone = enterprise_users[0]?.phone;
}
zaifuList.push({ zaifuList.push({
eId, eId,
enterpriseName, // 企业名称 enterpriseName, // 企业名称
uscc, // 统一信用代码 uscc, // 统一信用代码
phone,//登录手机号
logonTime: moment(logonTime).format("YYYY-MM-DD"), // 注册日期 logonTime: moment(logonTime).format("YYYY-MM-DD"), // 注册日期
logonAddress: changeAdd(JSON.parse(logonAddress)), // 注册地址 logonAddress: changeAdd(JSON.parse(logonAddress)), // 注册地址
qiYeGuiMo, // 企业规模 qiYeGuiMo, // 企业规模
......
...@@ -127,8 +127,8 @@ function getModel(name, type, otherStr?, code?) { ...@@ -127,8 +127,8 @@ function getModel(name, type, otherStr?, code?) {
if (!userInfo.mail) { if (!userInfo.mail) {
new BizError(ERRORENUM.该用户邮箱为空, eId, eId.enterpriseName); new BizError(ERRORENUM.该用户邮箱为空, eId, eId.enterpriseName);
} else { } else {
// let result = await send(userInfo.mail, userInfo.enterpriseName, type, otherStr); let result = await send(userInfo.mail, userInfo.enterpriseName, type, otherStr);
let result = "邮件发送成功" // let result = "邮件发送成功"
} }
return successResult(); return successResult();
......
...@@ -162,8 +162,212 @@ export async function settleInEnterpriseList(page:number, enterpriseName:string) ...@@ -162,8 +162,212 @@ export async function settleInEnterpriseList(page:number, enterpriseName:string)
* @param eId * @param eId
* @returns * @returns
*/ */
export async function settleInEnterprisePass(eId:string) { // export async function settleInEnterprisePass(eId:string) {
let filesList = ["eId", "enterpriseName", "uscc", "logonTime", "state"]; // 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); let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList);
if (!resInfo || !resInfo.eId) { if (!resInfo || !resInfo.eId) {
...@@ -187,12 +391,172 @@ export async function settleInEnterprisePass(eId:string) { ...@@ -187,12 +391,172 @@ export async function settleInEnterprisePass(eId:string) {
await operationalData( OPERATIONALDATATYPE.增加, TABLENAME.入孵申请审批表, addInfo, {} ); 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}; return {isSuccess:true};
} }
/** /**
* 入孵申请回显 * 入孵申请回显
* @param eId * @param eId
...@@ -308,6 +672,88 @@ export async function settleInEnterpriseUpdate(eId:string, param) { ...@@ -308,6 +672,88 @@ export async function settleInEnterpriseUpdate(eId:string, param) {
* @param desc * @param desc
* @returns * @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) { export async function settleInEnterpriseOut(eId:string, descType, desc:string) {
let filesList = ["eId", "enterpriseName", "uscc", "logonTime", "state", "emailReminder"]; let filesList = ["eId", "enterpriseName", "uscc", "logonTime", "state", "emailReminder"];
let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList); let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList);
...@@ -353,36 +799,333 @@ export async function settleInEnterpriseOut(eId:string, descType, desc:string) { ...@@ -353,36 +799,333 @@ export async function settleInEnterpriseOut(eId:string, descType, desc:string) {
mailStr += `<p>我们期待未来与贵公司的合作机会,衷心祝愿贵公司业务发展顺利!</p>`; mailStr += `<p>我们期待未来与贵公司的合作机会,衷心祝愿贵公司业务发展顺利!</p>`;
await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵申请, mailStr ); await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵申请, mailStr );
/**如果emailReminder为是,则设置7天后再次提醒 */ /**如果emailReminder为是,则设置周期性提醒机制 */
if (resInfo.emailReminder == enumConfig.STATE.) { // if (resInfo.emailReminder == enumConfig.STATE.是) {
setTimeout( async() => { // // 根据参数确定提醒间隔
try { // const REMINDER_INTERVAL = production === "production"
//检查企业状态是否仍然是已驳回(未重新提交) // ? 7 * 24 * 60 * 60 * 1000 // 生产环境:7天
let currentInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, ["register"]); // : 60 * 1000; // 测试环境:1分钟
if (currentInfo && currentInfo.register === enumConfig.CHANGESTATE.已驳回) {
let reminderMailStr = ""; // // 创建申请驳回的周期性提醒函数
reminderMailStr += "<p>【雨艺孵化器】入孵申请提醒</p>"; // const scheduleApplicationRejectionReminder = async () => {
reminderMailStr += "<p>尊敬的客户:</p>"; // try {
reminderMailStr += "<p>我们注意到您在7天前提交的入孵申请未通过初审,目前尚未收到您的重新提交。</p>"; // // 检查是否应该继续提醒
reminderMailStr += `<p>驳回原因:${descStr}</p>`; // const shouldContinue = await checkShouldContinueForApplicationRejection(eId);
reminderMailStr += "<p>如果您仍有入驻意向,请根据审核意见完善资料后重新提交申请。</p>";
reminderMailStr += "<p>如有任何疑问,欢迎随时联系我们。</p>"; // if (!shouldContinue) {
reminderMailStr += "<p>期待您的回复!</p>"; // console.log(`为企业 ${eId} 停止周期性入孵申请驳回提醒,时间:${new Date().toLocaleString()}`);
// return; // 终止循环
// }
await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵申请, reminderMailStr); // // 获取最新的企业状态
console.log(`7天后入孵申请驳回提醒邮件已发送给企业 ${resInfo.eId}`); // const currentInfo = await selectData(
} // OPERATIONALDATATYPE.查询单个,
} catch (error) { // TABLENAME.企业基础信息表,
console.error(`发送7天后入孵申请驳回提醒邮件失败:`, error); // {eId},
} // ["register"]
}, 7 * 24 * 60 * 60 * 1000); // 7天后的毫秒数 // );
}
// // 如果企业仍然是已驳回状态,发送提醒邮件
// 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}; 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() { export async function getNewApplicationCount() {
...@@ -500,6 +1243,7 @@ export async function enterpriseRegisterExamineList(enterpriseName, page) { ...@@ -500,6 +1243,7 @@ export async function enterpriseRegisterExamineList(enterpriseName, page) {
eId:info.eId, eId:info.eId,
enterpriseName:info.enterpriseName, enterpriseName:info.enterpriseName,
randomCode:info.randomCode, randomCode:info.randomCode,
emailReminder:info.emailReminder,
/**跳转用 - 文件链接 */ /**跳转用 - 文件链接 */
...fileDisplayInfo, ...fileDisplayInfo,
/**显示用 - 文件名称(显示第一个文件) */ /**显示用 - 文件名称(显示第一个文件) */
...@@ -763,16 +1507,323 @@ export async function enterpriseRegisterExaminePass(eId:string) { ...@@ -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 eId
* @param descType 驳回类型 [1, 2] * @param descType 驳回类型 [1, 2]
* @param desc * @param desc
* @returns * @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 (!eId) throw new BizError(ERRORENUM.参数错误);
if (!descType.length) 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); let resInfo = await selectData(OPERATIONALDATATYPE.查询单个, TABLENAME.企业基础信息表, {eId}, filesList);
if (!resInfo || !resInfo.eId) throw new BizError(ERRORENUM.数据不存在); if (!resInfo || !resInfo.eId) throw new BizError(ERRORENUM.数据不存在);
...@@ -825,33 +1876,150 @@ export async function enterpriseRegisterExamineOut(eId:string, descType, desc:st ...@@ -825,33 +1876,150 @@ export async function enterpriseRegisterExamineOut(eId:string, descType, desc:st
mailStr += `<p>感谢理解与配合!</p>`; mailStr += `<p>感谢理解与配合!</p>`;
await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵材料申请, mailStr ); await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵材料申请, mailStr );
/**设置7天后再次提醒 */ /**如果emailReminder为是,则设置周期性提醒机制 */
setTimeout(async () => { if (resInfo.emailReminder == enumConfig.STATE.) {
// 根据参数确定提醒间隔
const REMINDER_INTERVAL = production === "production"
? 7 * 24 * 60 * 60 * 1000 // 生产环境:7天
: 60 * 1000; // 测试环境:1分钟
// 创建材料驳回的周期性提醒函数
const scheduleMaterialRejectionReminder = async () => {
try { 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.已驳回) { if (currentInfo && currentInfo.state === enumConfig.CHANGESTATE.已驳回) {
let reminderMailStr = ""; let reminderMailStr = "";
reminderMailStr += "<p>【雨艺孵化器】入孵材料审核提醒</p>"; reminderMailStr += "<p>【雨艺孵化器】入孵材料审核提醒</p>";
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>驳回原因:${descStr}</p>`;
reminderMailStr += "<p>请您根据审核意见尽快完善相关材料并重新提交,以便我们继续为您处理入孵申请。</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>";
reminderMailStr += "<p>期待您的完善材料!</p>"; reminderMailStr += "<p>期待您的完善材料!</p>";
await systemSendMail(resInfo.eId, enumConfig.MAILTYPE.驳回入孵材料申请, reminderMailStr); await systemSendMail(eId, enumConfig.MAILTYPE.驳回入孵材料申请, reminderMailStr);
console.log(`7天后入孵材料驳回提醒邮件已发送给企业 ${resInfo.eId}`); 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) { } 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}; return {isSuccess:true};
} }
/** /**
* 编辑入孵材料 * 编辑入孵材料
* @param eId * @param eId
......
...@@ -3,14 +3,14 @@ ...@@ -3,14 +3,14 @@
*/ */
import moment = require("moment"); import moment = require("moment");
import { OPERATIONALDATATYPE, TABLENAME } from "../config/enum/dbEnum"; import { OPERATIONALDATATYPE, TABLEID, TABLENAME } from "../config/enum/dbEnum";
import { operationalData, paginateArray, selectData, selectManyTableData } from "../data/operationalData"; import { operationalData, paginateArray, selectData, selectManyTableData } from "../data/operationalData";
import { changeAdd } from "../util/piecemeal"; import { changeAdd } from "../util/piecemeal";
import { changeEnumManyValue, changeEnumValue } from "../util/verificationEnum"; import { changeEnumManyValue, changeEnumValue } from "../util/verificationEnum";
import * as enumConfig from "../config/enum/enum"; import * as enumConfig from "../config/enum/enum";
import { BizError } from "../util/bizError"; import { BizError } from "../util/bizError";
import { ERRORENUM } from "../config/enum/errorEnum"; 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"; import { BUILDING } from "../config/enum/enum";
...@@ -234,6 +234,77 @@ export async function enterpriseMigrateList(enterpriseName:string, page:number) ...@@ -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 * @param eId
*/ */
......
...@@ -288,7 +288,8 @@ export enum CHANGESTATE { ...@@ -288,7 +288,8 @@ export enum CHANGESTATE {
*/ */
export enum CHANGETYPE { export enum CHANGETYPE {
入孵申请 = 1, 入孵申请 = 1,
入孵材料审批 = 2 入孵材料审批 = 2,
返回在孵 = 3,
} }
......
...@@ -44,7 +44,8 @@ export enum ERRORENUM { ...@@ -44,7 +44,8 @@ export enum ERRORENUM {
请选择驳回原因, 请选择驳回原因,
原密码错误, 原密码错误,
密码不一致, 密码不一致,
系统错误 系统错误,
该企业当前不在迁出状态
} }
export enum ERRORCODEENUM { export enum ERRORCODEENUM {
......
...@@ -14,7 +14,7 @@ async function lanuch() { ...@@ -14,7 +14,7 @@ async function lanuch() {
httpServer.createServer(systemConfig.port); httpServer.createServer(systemConfig.port);
console.log('This indicates that the server is started successfully.'); console.log('This indicates that the server is started successfully.');
// await initApiDataStorage(); await initApiDataStorage();
// console.log("更新加密后密码格式..."); // console.log("更新加密后密码格式...");
// await migrateEnterpriseUserPasswords(); // await migrateEnterpriseUserPasswords();
......
...@@ -35,6 +35,7 @@ export function setRouter(httpServer) { ...@@ -35,6 +35,7 @@ export function setRouter(httpServer) {
httpServer.post('/admin/enterprise/settlein/examine/list', checkUser, asyncHandler(examineSettleIn)); 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/pass', checkUser, asyncHandler(examineSettleInPass)); //入孵材料审核 通过
httpServer.post('/admin/enterprise/settlein/examine/out', checkUser, asyncHandler(examineSettleInOut)); //驳回 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)); httpServer.post('/admin/notice/list', checkUser, asyncHandler(noticeList));
...@@ -53,6 +54,7 @@ export function setRouter(httpServer) { ...@@ -53,6 +54,7 @@ export function setRouter(httpServer) {
httpServer.post('/admin/library/enterprise/list', checkUser, asyncHandler(enterpriseList)); 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/out', checkUser, asyncHandler(enterpriseMigrateOut));//在孵企业迁出功能
httpServer.post('/admin/library/enterprise/migrate/list', checkUser, asyncHandler(enterpriseMigrateList));//迁出企业列表 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/details', checkUser, asyncHandler(enterpriseDetails));
httpServer.post('/admin/library/enterprise/resetpwd', checkUser, asyncHandler(resetPwd)); httpServer.post('/admin/library/enterprise/resetpwd', checkUser, asyncHandler(resetPwd));
// httpServer.post('/admin/library/enterprise/details', checkUser, asyncHandler(enterpriseById)); // httpServer.post('/admin/library/enterprise/details', checkUser, asyncHandler(enterpriseById));
...@@ -393,6 +395,21 @@ async function enterpriseMigrateList(req, res) { ...@@ -393,6 +395,21 @@ async function enterpriseMigrateList(req, res) {
res.success(result); 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 * @param req
...@@ -820,20 +837,20 @@ async function settleIn(req, res) { ...@@ -820,20 +837,20 @@ async function settleIn(req, res) {
/** /**
* * 入孵申请通过
* @param req * @param req
* @param res * @param res
*/ */
async function settleInPass(req, res) { async function settleInPass(req, res) {
const UserInfo = req.userInfo; const UserInfo = req.userInfo;
let { eId } = req.body let { eId } = req.body
let result = await ruFuBiz.settleInEnterprisePass(eId); let result = await ruFuBiz.settleInEnterprisePass(eId, "production");
res.success(result); res.success(result);
} }
/** /**
* * 入孵申请回显
* @param req * @param req
* @param res * @param res
*/ */
...@@ -847,7 +864,7 @@ async function settleInById(req, res) { ...@@ -847,7 +864,7 @@ async function settleInById(req, res) {
/** /**
* * 入孵申请驳回
* @param req * @param req
* @param res * @param res
*/ */
...@@ -966,8 +983,20 @@ async function examineSettleInPass(req, res) { ...@@ -966,8 +983,20 @@ async function examineSettleInPass(req, res) {
async function examineSettleInOut(req, res) { async function examineSettleInOut(req, res) {
const UserInfo = req.userInfo; const UserInfo = req.userInfo;
let { eId, descType, desc } = req.body; 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); res.success(result);
} }
......
...@@ -23,8 +23,8 @@ export function setRouter(httpServer) { ...@@ -23,8 +23,8 @@ export function setRouter(httpServer) {
*/ */
async function ledgerList(req, res) { async function ledgerList(req, res) {
const UserInfo = req.userInfo; const UserInfo = req.userInfo;
let {enterpriseName, logonStartTime, logonEndTime, building, page } = req.body let {enterpriseName, phone, logonStartTime, logonEndTime, building, page } = req.body
let result = await ledgerBiz.ledgerList(enterpriseName, logonStartTime, logonEndTime, building, page); let result = await ledgerBiz.ledgerList(enterpriseName, phone, logonStartTime, logonEndTime, building, page);
res.success(result); res.success(result);
} }
......
...@@ -13,7 +13,6 @@ export function setRouter(httpServer) { ...@@ -13,7 +13,6 @@ export function setRouter(httpServer) {
httpServer.post('/admin/enterprise/rufu/settleininfo', asyncHandler(settleInById)); httpServer.post('/admin/enterprise/rufu/settleininfo', asyncHandler(settleInById));
httpServer.post('/admin/enterprise/rufu/info', asyncHandler(getRuFu)); httpServer.post('/admin/enterprise/rufu/info', asyncHandler(getRuFu));
httpServer.post('/admin/enterprise/rufu/update', asyncHandler(updateRuFu)); httpServer.post('/admin/enterprise/rufu/update', asyncHandler(updateRuFu));
} }
...@@ -23,7 +22,7 @@ export function setRouter(httpServer) { ...@@ -23,7 +22,7 @@ export function setRouter(httpServer) {
* @param res * @param res
*/ */
async function register(req, 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); let result = await userRuFuBiz.enterpriseRegister(userName, phone, pwd);
res.success(result); res.success(result);
} }
...@@ -35,20 +34,19 @@ export function setRouter(httpServer) { ...@@ -35,20 +34,19 @@ export function setRouter(httpServer) {
* @param res * @param res
*/ */
async function login(req, res) { async function login(req, res) {
let {phone, pwd } = req.body let { phone, pwd } = req.body
let result = await userRuFuBiz.enterpriseLogin(phone, pwd); let result = await userRuFuBiz.enterpriseLogin(phone, pwd);
res.success(result); res.success(result);
} }
/** /**
* 获取入孵流程状态 * 获取入孵流程状态
* @param req * @param req
* @param res * @param res
*/ */
async function ruFuState(req, res) { async function ruFuState(req, res) {
let {uId } = req.body let { uId } = req.body
let result = await userRuFuBiz.getRuFuState(uId); let result = await userRuFuBiz.getRuFuState(uId);
res.success(result); res.success(result);
} }
...@@ -66,8 +64,9 @@ export function setRouter(httpServer) { ...@@ -66,8 +64,9 @@ export function setRouter(httpServer) {
res.success(result); res.success(result);
} }
/** /**
* * 入孵申请回显
* @param req * @param req
* @param res * @param res
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment