Commit d9e89abe by lixinming

Merge branch 'master' of http://123.207.147.179:8888/node_server/zhangjiangzhenxcxserver

# Conflicts:
#	res/标记企业12_10.xlsx
#	src/config/enum.ts
#	src/config/errorEnum.ts
#	src/db/mongo/tableInit.ts
#	src/routers/public.ts
parents 8f823bf1 c1530a0a
......@@ -405,7 +405,7 @@ export async function enterpriseBusinessList(selectStr:string, industry:number,
/**
* 导出经营数据(支持动态列配置)todo
* 导出经营数据(支持动态列配置)
* @param param0
* @returns
*/
......
/**
* 空间管理
*/
import moment = require("moment");
import { DELIVERYSTANDARD } from "../config/enum";
import { ERRORENUM } from "../config/errorEnum";
import { AddSpaceConfig } from "../config/paramConfig";
import * as spaceData from "../data/space";
import { convertFilesToObjectArray, getInformationId, successResult } from "../tools/system";
import { BizError } from "../util/bizError";
import { changeEnumValue } from "../util/verificationEnum";
import { eccFormParam } from "../util/verificationParam";
/**
* 空间管理列表
* @param name
* @param page
* @returns
*/
export async function spaceList(name:string, page:number) {
let param:any = {};
if (name) {
param.name = {"$regex":name};
}
let list = await spaceData.findSpaceListPageByParam(param, page);
let dataCount = await spaceData.findSpaceCount(param);
let dataList = [];
list.forEach(info => {
let item = {
spaceId: info.spaceId,
name: info.name, // 物业名称
address: info.address || "-", // 地址
totalArea: info.totalArea || "-", // 总面积(平方米)
leasingRate: info.leasingRate || "-", // 出租率(0-100之间的数字)%
vacantAreas: info.vacantAreas || [], // 空置区域(如:183.6m²4楼)
supportPolicies: info.supportPolicies || [], // 支持政策:孵化器补贴、青创15条等
description: info.description || "-", // 简介或项目描述
// 空间规格信息
spaceType: info.spaceType || "-", // 空间属性
environmentalAssessment: info.environmentalAssessment || "-", // 环评
deliveryStandard: changeEnumValue(DELIVERYSTANDARD, info.deliveryStandard), // 交付标准
deliveryRemark: info.deliveryRemark || "-", // 交付备注说明
floorHeight: info.floorHeight || "-", // 层高(m)
floorLoad: info.floorLoad || "-", // 承重(KN/m²)
standardFloorArea: info.standardFloorArea || "-", // 标准层面积(m²)
minLeasableArea: info.minLeasableArea || "-", // 最小可租面积(m²)
powerSupply: info.powerSupply || "-", // 电量(w/㎡)
parkingSpaces: info.parkingSpaces || "-", // 停车位数量
parkingFee: info.parkingFee || "-", // 停车费
deliveryTime: moment(info.deliveryTime).format("YYYY-MM-DD") || "-", // 交付时间 时间戳
contactPerson: info.contactPerson || "-", // 项目联系人
surroundingFacilities: info.surroundingFacilities || "-", // 周边配套
attachments: convertFilesToObjectArray(info.attachments), //附件信息
remark: info.remark || "-", //备注
};
dataList.push(item);
});
return {dataList, dataCount};
}
/**
* 新增空间
* @param reqUser
* @param param
* @returns
*/
export async function addSpace(param) {
const FunName = "管理后台=>新增空间";
eccFormParam(FunName, AddSpaceConfig, param);
let spaceInfo = await spaceData.findSpaceByName(param.name);
if (spaceInfo.name) throw new BizError(ERRORENUM.空间已存在);
param.spaceId = getInformationId();
param.createdAt = Date.now();;
param.updatedAt = Date.now();
param.vacantAreas = param.vacantAreas;
param.supportPolicies = param.supportPolicies;
await spaceData.addSpace(param);
return successResult();
}
/**
* 空间=>回显
* @param spaceId
* @returns
*/
export async function getSpaceInfo(spaceId:string) {
const FunName = "空间记录回显记录"
let spaceInfo = await spaceData.findSpaceById(spaceId);
if (!spaceInfo || !spaceInfo.spaceId) throw new BizError(ERRORENUM.空间不存在);
let dataInfo = {
spaceId: spaceInfo.spaceId,
name: spaceInfo.name, // 物业名称
address: spaceInfo.address || "-", // 地址
totalArea: spaceInfo.totalArea || "-", // 总面积(平方米)
leasingRate: spaceInfo.leasingRate || "-", // 出租率(0-100之间的数字)%
vacantAreas: spaceInfo.vacantAreas || [], // 空置区域(如:183.6m²4楼)
supportPolicies: spaceInfo.supportPolicies || [], // 支持政策:孵化器补贴、青创15条等
description: spaceInfo.description || "-", // 简介或项目描述
// 空间规格信息
spaceType: spaceInfo.spaceType || "-", // 空间属性
environmentalAssessment: spaceInfo.environmentalAssessment || "-", // 环评
deliveryStandard: changeEnumValue(DELIVERYSTANDARD, spaceInfo.deliveryStandard), // 交付标准
deliveryRemark: spaceInfo.deliveryRemark || "-", // 交付备注说明
floorHeight: spaceInfo.floorHeight || "-", // 层高(m)
floorLoad: spaceInfo.floorLoad || "-", // 承重(KN/m²)
standardFloorArea: spaceInfo.standardFloorArea || "-", // 标准层面积(m²)
minLeasableArea: spaceInfo.minLeasableArea || "-", // 最小可租面积(m²)
powerSupply: spaceInfo.powerSupply || "-", // 电量(w/㎡)
parkingSpaces: spaceInfo.parkingSpaces || "-", // 停车位数量
parkingFee: spaceInfo.parkingFee || "-", // 停车费
deliveryTime: moment(spaceInfo.deliveryTime).format("YYYY-MM-DD") || "-", // 交付时间 时间戳
contactPerson: spaceInfo.contactPerson || "-", // 项目联系人
surroundingFacilities: spaceInfo.surroundingFacilities || "-", // 周边配套
attachments: convertFilesToObjectArray(spaceInfo.attachments), //附件信息
remark: spaceInfo.remark || "-", //备注
}
return {dataInfo};
}
/**
* 空间=>修改
* @param spaceId
* @param param
* @returns
*/
export async function spaceUpdate(spaceId, param) {
let FunName = "管理后台修改空间";
eccFormParam(FunName, AddSpaceConfig, param);
let spaceInfo = await spaceData.findSpaceById(spaceId);
if (!spaceInfo || !spaceInfo.spaceId) throw new BizError(ERRORENUM.空间不存在);
for (let key in param) {
spaceInfo[key] = param[key]
}
await spaceInfo.save();
return successResult();
}
/**
* 删除空间
* @param spaceId
* @returns
*/
export async function spaceDel(spaceId) {
let spaceInfo = await spaceData.findSpaceById(spaceId);
if (!spaceInfo || !spaceInfo.spaceId) throw new BizError(ERRORENUM.空间不存在);
await spaceData.deleteOneSpace({spaceId});
return successResult();
}
// =================================小程序====================================
/**
* 空间管理列表
* @param name
* @param page
* @returns
*/
export async function spaceXCXList(name:string) {
let param:any = {};
if (name) {
param.name = {"$regex":name};
}
let list = await spaceData.findSpaceList(param);
let dataList = [];
list.forEach(info => {
let item = {
spaceId: info.spaceId,
attachments: convertFilesToObjectArray(info.attachments), //附件信息
name: info.name, // 物业名称
address: info.address || "-", // 地址
totalArea: info.totalArea || "-", // 总面积(平方米)
leasingRate: info.leasingRate || "-", // 出租率(0-100之间的数字)%
};
dataList.push(item);
});
return {dataList};
}
/**
* 空间=>回显
* @param spaceId
* @returns
*/
export async function getSpaceXCXInfo(spaceId:string) {
const FunName = "小程序-空间记录回显记录"
let spaceInfo = await spaceData.findSpaceById(spaceId);
if (!spaceInfo || !spaceInfo.spaceId) throw new BizError(ERRORENUM.空间不存在);
let dataInfo = {
spaceId: spaceInfo.spaceId,
name: spaceInfo.name, // 物业名称
address: spaceInfo.address || "-", // 地址
totalArea: spaceInfo.totalArea || "-", // 总面积(平方米)
leasingRate: spaceInfo.leasingRate || "-", // 出租率(0-100之间的数字)%
vacantAreas: spaceInfo.vacantAreas || [], // 空置区域(如:183.6m²4楼)
supportPolicies: spaceInfo.supportPolicies || [], // 支持政策:孵化器补贴、青创15条等
description: spaceInfo.description || "-", // 简介或项目描述
// 空间规格信息
spaceType: spaceInfo.spaceType || "-", // 空间属性
environmentalAssessment: spaceInfo.environmentalAssessment || "-", // 环评
deliveryStandard: changeEnumValue(DELIVERYSTANDARD, spaceInfo.deliveryStandard), // 交付标准
deliveryRemark: spaceInfo.deliveryRemark || "-", // 交付备注说明
floorHeight: spaceInfo.floorHeight || "-", // 层高(m)
floorLoad: spaceInfo.floorLoad || "-", // 承重(KN/m²)
standardFloorArea: spaceInfo.standardFloorArea || "-", // 标准层面积(m²)
minLeasableArea: spaceInfo.minLeasableArea || "-", // 最小可租面积(m²)
powerSupply: spaceInfo.powerSupply || "-", // 电量(w/㎡)
parkingSpaces: spaceInfo.parkingSpaces || "-", // 停车位数量
parkingFee: spaceInfo.parkingFee || "-", // 停车费
deliveryTime: spaceInfo.deliveryTime || "-", // 交付时间 时间戳
contactPerson: spaceInfo.contactPerson || "-", // 项目联系人
surroundingFacilities: spaceInfo.surroundingFacilities || "-", // 周边配套
attachments: convertFilesToObjectArray(spaceInfo.attachments), //附件信息
remark: spaceInfo.remark || "-", //备注
}
return {dataInfo};
}
/**
* 空间=>修改出租率
* @param spaceId
* @param param
* @returns
*/
export async function spaceUpdateLeasingRate(spaceId, leasingRate) {
let FunName = "管理后台修改空间出租率";
eccFormParam(FunName, {leasingRate:{type:"Number"}}, {leasingRate});
let spaceInfo = await spaceData.findSpaceById(spaceId);
if (!spaceInfo || !spaceInfo.spaceId) throw new BizError(ERRORENUM.空间不存在);
spaceInfo["leasingRate"] = leasingRate;
await spaceInfo.save();
return successResult();
}
......@@ -409,3 +409,17 @@ export enum YONGFANGTYPE {
自有用房 = 1,
租赁用房
}
export enum DELIVERYSTANDARD {
简装 = 1,
精装,
}
......@@ -18,7 +18,8 @@ export enum ERRORENUM {
政策不存在,
政策落实不存在,
本年度数据已存在,
智能体调用出错请联系管理员
智能体调用出错请联系管理员,
空间不存在,
}
......
......@@ -339,3 +339,32 @@ export const AdminUpdateOverallOperationConfig = {
}
/**
* 添加 空间
*/
export const AddSpaceConfig = {
name:{type:"String"}, //物业名称
address:{type:"String"}, // 地址
totalArea:{type:"Number"}, // 总面积(平方米)
leasingRate:{type:"Number"}, // 出租率
vacantAreas:{type:"[]"}, // 空置区域
supportPolicies:{type:"[]"}, // 支持政策
description:{type:"String"}, // 简介或项目描述
spaceType:{type:"String"}, // 空间属性
environmentalAssessment:{type:"String"}, // 环评
deliveryStandard:{type:"Number"}, // 交付标准
deliveryRemark:{type:"String", notMustHave:true}, // 交付备注说明
floorHeight:{type:"String"}, // 层高(m)
floorLoad:{type:"String"}, // 承重(KN/m²)
standardFloorArea:{type:"String"}, // 标准层面积(m²)
minLeasableArea:{type:"String"}, // 最小可租面积(m²)
powerSupply:{type:"String"}, // 电量(w/㎡)
parkingSpaces:{type:"String"}, // 停车位数量
parkingFee:{type:"String"}, // 停车费
deliveryTime:{type:"Number", notMustHave:true}, // 交付时间 时间戳
contactPerson:{type:"String", notMustHave:true}, // 项目联系人
surroundingFacilities:{type:"String", notMustHave:true}, // 周边配套
attachments:{type:"[]"}, // 附件信息 JSON格式(如:["1.jpg", "2.jpg"])
remark:{type:"String", notMustHave:true}, // 备注
}
/**
* 空间管理
*/
import {Schema} from 'mongoose';
import { baseDB } from '../db/mongo/dbInit';
/**
* 空置区域
*/
// const vacantAreaSchema = new Schema({
// vaId:String,
// area:Number, // 面积(平方米)(如:183.6m²)
// floor:Number, //楼层(如:4楼)
// },{_id:false});
/**
* 支持政策
*/
// const supportPoliciesSchema = new Schema({
// spId:String,
// name:String, // 对应政策
// remark:String, //备注说明
// },{_id:false});
const spaceSchema = new Schema({
// 基础信息
spaceId: {type:String, index:true}, // 空间唯一ID
name: String, // 物业名称
address: String, // 地址
totalArea: Number, // 总面积(平方米)
leasingRate: Number, // 出租率(0-100之间的数字)%
vacantAreas: {type:[String], default:[]}, // 空置区域 JSON格式(如:["183.6m²4楼", ""])
// vacantAreas:{type:[vacantAreaSchema], default:[]},//空置区域
supportPolicies: {type:[String], default:[]}, // 支持政策 JSON格式(如:["孵化器补贴", "青创15条"])
// supportPolicies:{type:[supportPoliciesSchema], default:[]},//支持政策
description: String, // 简介或项目描述
// 规格信息(来自第二张表)
spaceType: String, // 空间属性
environmentalAssessment: String, // 环评
deliveryStandard: Number, // 交付标准 DELIVERYSTANDARD
deliveryRemark: String, //交付备注说明
floorHeight: String, // 层高(m)
floorLoad: String, // 承重(KN/m²)
standardFloorArea: String, // 标准层面积(m²)可能是区间范围(如:1100-2200㎡)
minLeasableArea: String, // 最小可租面积(m²)
powerSupply: String, // 电量(w/㎡)
parkingSpaces: String, // 停车位数量
parkingFee: String, // 停车费 元/个
deliveryTime: Number, // 交付时间 时间戳
contactPerson: String, // 项目联系人
surroundingFacilities: String, // 周边配套
attachments: {type:[String], default:[]}, // 附件信息 JSON格式(如:["1.jpg", "2.jpg"])
remark: String, // 备注
// 系统字段
createdAt: Number,
updatedAt: Number
});
var spaceModel: any;
export function initModel(){
spaceModel = baseDB.model('space', spaceSchema);
// 扩展模型方法:选择单个数据并绑定save方法
spaceModel.selectOnceData = async function (parameter: object) {
let selectInfo = await spaceModel.findOne(parameter).exec();
if (selectInfo) {
if (!selectInfo.runSave) {
selectInfo.runSave = selectInfo.save;
selectInfo.save = save.bind(selectInfo)
}
}
return selectInfo;
}
return spaceModel;
}
// 自定义保存方法
export async function save(throwError=false) {
if (!this.isModified()) return;
this.updatedAt = Date.now();
await this.runSave({validateBeforeSave:false}).catch(err=>{
console.log(err);
if (throwError) throw err;
});
}
// ============ CRUD 操作方法 ============
/**
* 查询空间列表
* @param param 查询条件
*/
export async function findSpaceList(param: object) {
return await spaceModel.find(param);
}
/**
* 分页查询空间列表
* @param param 查询条件
* @param skipCount 页码
* @param pageSize 每页数量,默认10
*/
export async function findSpaceListPageByParam(param, skipCount) {
return await spaceModel.find(param).skip((skipCount-1)*10).limit(10);
}
/**
* 查询空间数量
* @param param 查询条件
*/
export async function findSpaceCount(param: object) {
return await spaceModel.countDocuments(param);
}
/**
* 查询单个空间详情
* @param param 查询条件
*/
export async function findOneSpace(param: object) {
return await spaceModel.selectOnceData(param);
}
/**
* 创建空间
* @param param 空间数据
*/
export async function addSpace(param: object) {
return await spaceModel.create(param);
}
/**
* 删除单个空间
* @param param 删除条件
*/
export async function deleteOneSpace(param: object) {
return await spaceModel.deleteOne(param);
}
/**
* 更新空间信息
* @param filter 查询条件
* @param updateData 更新数据
*/
export async function updateSpace(filter: object, updateData: object) {
return await spaceModel.updateOne(filter, updateData);
}
/**
* 批量更新空间
* @param filter 查询条件
* @param updateData 更新数据
*/
export async function updateManySpaces(filter: object, updateData: object) {
const data = {
...updateData,
updatedAt: Date.now()
};
return await spaceModel.updateMany(filter, data).exec();
}
/**
* 根据ID查询空间
* @param spaceId 空间ID
*/
export async function findSpaceById(spaceId: string) {
return await spaceModel.selectOnceData({ spaceId });
}
/**
* 根据名称模糊查询空间
* @param name 空间名称关键词
*/
export async function findSpaceByName(name: string) {
const regex = new RegExp(name, 'i'); // 不区分大小写
return await spaceModel.find({ name: regex }).exec();
}
/**
* 查询有空置区域的空间
*/
export async function findVacantSpaces() {
return await spaceModel.find({
$or: [
{ vacantAreas: { $exists: true, $ne: [] } },
{ leasingRate: { $lt: 100 } }
]
}).exec();
}
/**
* 根据出租率范围查询空间
* @param minRate 最小出租率
* @param maxRate 最大出租率
*/
export async function findSpaceByLeasingRate(minRate: number, maxRate: number) {
return await spaceModel.find({
leasingRate: { $gte: minRate, $lte: maxRate }
}).exec();
}
......@@ -12,7 +12,8 @@ import * as userModel from "../../data/user";
import * as dynamicModel from "../../data/service/dynamic";
import * as appealsModel from "../../data/service/appeals";
import * as visitPlanModel from "../../data/service/visitPlan";
import * as overallOperationModel from "../../data/overallOperation"
import * as overallOperationModel from "../../data/overallOperation";
import * as spaceModel from "../../data/space";
import * as yingShouModel from "../../data/enterprise/yingShou"
import * as zdzsfwModel from "../../data/enterprise/zdzsfw"
......@@ -37,4 +38,5 @@ export async function initTable() {
overallOperationModel.initModel();
yingShouModel.initModel();
zdzsfwModel.initModel();
spaceModel.initModel();
}
\ No newline at end of file
/**
* 空间管理
*/
import asyncHandler = require('express-async-handler');
import { eccReqParamater } from '../../util/verificationParam';
import * as spaceBiz from '../../biz/space';
import { checkAdminToken, checkToken } from '../../middleware/user';
export function setRouter(httpServer) {
httpServer.post('/zj/admin/service/space/list', checkAdminToken, asyncHandler(space_list));//空间管理-列表
httpServer.post('/zj/admin/service/space/add', checkAdminToken, asyncHandler(space_add));//空间管理-新增
httpServer.post('/zj/admin/service/space/info', checkAdminToken, asyncHandler(space_info));//空间管理-回显
httpServer.post('/zj/admin/service/space/update', checkAdminToken, asyncHandler(space_update));//空间管理-修改
httpServer.post('/zj/admin/service/space/del', checkAdminToken, asyncHandler(space_del));//空间管理-删除
}
async function space_list(req, res) {
let reqConf = {name:'String', page:'Number' };
const NotMustHaveKeys = ["name"];
let { name, page } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await spaceBiz.spaceList(name, page);
res.success(result);
}
async function space_add(req, res) {
let reqConf = {param:'Object'};
let { param } = eccReqParamater(reqConf, req.body);
let result = await spaceBiz.addSpace(param);
res.success(result);
}
async function space_info(req, res) {
let reqConf = {spaceId:'String'};
let { spaceId } = eccReqParamater(reqConf, req.body);
let result = await spaceBiz.getSpaceInfo(spaceId);
res.success(result);
}
async function space_update(req, res) {
let reqConf = { spaceId:"String", param:"Object" };
const NotMustHaveKeys = [""];
let { spaceId, param } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let data = await spaceBiz.spaceUpdate(spaceId, param);
res.success(data);
}
async function space_del(req, res) {
let reqConf = {spaceId:'String'};
let { spaceId } = eccReqParamater(reqConf, req.body);
let result = await spaceBiz.spaceDel(spaceId);
res.success(result);
}
/**
* 空间管理
*/
import asyncHandler = require('express-async-handler');
import { eccReqParamater } from '../../util/verificationParam';
import * as spaceBiz from '../../biz/space';
import { checkToken } from '../../middleware/user';
export function setRouter(httpServer) {
httpServer.post('/zj/xcx/enterprisemanage/space/list', checkToken, asyncHandler(space_list));//空间管理-列表
httpServer.post('/zj/xcx/enterprisemanage/space/info', checkToken, asyncHandler(space_info));//空间管理-回显
httpServer.post('/zj/xcx/enterprisemanage/space/updaterate', checkToken, asyncHandler(space_updateLeasingRate));//空间管理-修改出租率
}
async function space_list(req, res) {
let reqConf = {name:'String' };
const NotMustHaveKeys = ["name"];
let { name } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await spaceBiz.spaceXCXList(name);
res.success(result);
}
async function space_info(req, res) {
let reqConf = {spaceId:'String'};
let { spaceId } = eccReqParamater(reqConf, req.body);
let result = await spaceBiz.getSpaceXCXInfo(spaceId);
res.success(result);
}
async function space_updateLeasingRate(req, res) {
let reqConf = { spaceId:"String", leasingRate:"Number" };
const NotMustHaveKeys = [""];
let { spaceId, leasingRate } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let data = await spaceBiz.spaceUpdateLeasingRate(spaceId, leasingRate);
res.success(data);
}
......@@ -41,6 +41,7 @@ const config = {
"/zj/admin/public/implementclient":enumConfig.IMPLEMENTCLIENT,
"/zj/admin/public/sixlist":enumConfig.SIXLIST,//六清单类型
"/zj/admin/public/deliverystandard":enumConfig.DELIVERYSTANDARD,
/**导出数据列 */
"/zj/admin/public/outputcolumns/enterprise":outputConfig.ENTERPRISECOLUMNS,
......
......@@ -12,6 +12,8 @@ import * as serviceRouters from './enterpriseButler/service';
import * as userRouters from './enterpriseButler/user';
import * as adminUserRouters from './admin/user';
import * as adminRouters from './admin/admin';
import * as spaceRouters from './admin/space';
import * as xcxspaceRouters from './enterpriseButler/space';
export function setRouter(httpServer){
......@@ -27,4 +29,8 @@ export function setRouter(httpServer){
userRouters.setRouter(httpServer);
adminUserRouters.setRouter(httpServer);
adminRouters.setRouter(httpServer);
adminRouters.setRouter(httpServer);
adminRouters.setRouter(httpServer);
spaceRouters.setRouter(httpServer);
xcxspaceRouters.setRouter(httpServer);
}
\ No newline at end of file
......@@ -204,3 +204,187 @@ export function changeAddressListToStr(addressList) {
});
return str;
}
/**
* 安全解析 JSON 或处理 Mongoose 数组并转换为对象数组
* @param fileInput - 可以是 JSON 字符串、数组或 Mongoose 数组
* @returns
*/
export function convertFilesToObjectArray(fileInput: any) {
const defaultResult: Array<{ name: string; url: string }> = [];
// 如果值为 null、undefined 或空字符串,返回空数组
if (fileInput === null || fileInput === undefined || fileInput === '' || fileInput === '""') {
return defaultResult;
}
let fileUrls: string[];
try {
// 情况1:已经是数组
if (Array.isArray(fileInput)) {
fileUrls = fileInput;
}
// 情况2:是 Mongoose 数组(CoreMongooseArray)
else if (fileInput && typeof fileInput === 'object' && fileInput.toObject) {
// 将 Mongoose 数组转换为普通数组
fileUrls = fileInput.toObject();
}
// 情况3:是字符串(JSON)
else if (typeof fileInput === 'string') {
// 直接尝试解析 JSON
const parsed = JSON.parse(fileInput);
// 检查解析后是否为数组
if (!Array.isArray(parsed)) {
console.warn('解析后的 JSON 不是数组:', parsed);
return defaultResult;
}
fileUrls = parsed;
}
// 情况4:其他类型,尝试直接使用
else {
console.warn('不支持的文件输入类型:', typeof fileInput, fileInput);
return defaultResult;
}
// 再次确保是数组
if (!Array.isArray(fileUrls)) {
console.warn('最终结果不是数组:', fileUrls);
return defaultResult;
}
// 过滤掉 null/undefined/空字符串
const validUrls = fileUrls.filter(url =>
url !== null &&
url !== undefined &&
url !== '' &&
typeof url === 'string'
);
// 转换为对象数组
return validUrls.map((url, index) => {
const urlParts = url.split('/');
const originalFileName = urlParts[urlParts.length - 1];
// 提取文件名(根据您的示例数据格式)
let fileName = originalFileName;
// 提取扩展名
const extensionMatch = originalFileName.match(/\.\w+$/);
const extension = extensionMatch ? extensionMatch[0] : '';
// 如果文件名没有扩展名,直接返回
if (!extension) {
return {
name: originalFileName,
url: url
};
}
// 获取不带扩展名的文件名
const nameWithoutExt = fileName.slice(0, -extension.length);
// 针对你的具体格式进行智能处理
// 例如:三方协议2025.8.1820250902_163174.pdf
// 应该变成:三方协议2025.8.18.pdf
let cleanedName = nameWithoutExt;
// 方法1:智能识别并移除时间戳部分
// 查找类似 20250902_163174 这样的时间戳模式
const timestampPatterns = [
/\d{8}_\d{5,6}$/, // YYYYMMDD_HHMMSS 或 YYYYMMDD_HHMM
/\d{14}$/, // YYYYMMDDHHMMSS
/\d{12}$/, // YYYYMMDDHHMM
/\d{10}$/, // YYYYMMDDHH
/\d{8}$/, // YYYYMMDD(在末尾时)
];
// 检查文件名中是否有版本号+时间戳的组合
// 例如:2025.8.18 + 20250902_163174
for (const pattern of timestampPatterns) {
if (pattern.test(cleanedName)) {
// 找到时间戳的起始位置
const timestampMatch = cleanedName.match(pattern);
if (timestampMatch) {
const timestamp = timestampMatch[0];
const timestampIndex = cleanedName.lastIndexOf(timestamp);
// 检查时间戳前是否有重复的日期部分
const beforeTimestamp = cleanedName.substring(0, timestampIndex);
// 如果时间戳前有类似格式的内容,可能是重复的,移除时间戳
if (beforeTimestamp.endsWith('2025.8.18') ||
beforeTimestamp.endsWith('2025.8')) {
cleanedName = beforeTimestamp;
break;
}
}
}
}
// 方法2:处理特定的重复模式
// 对于 "2025.8.1820250902_163174" 这样的模式
const yearMonthDayRegex = /(20\d{2}\.\d{1,2}\.\d{1,2})\1?/;
if (yearMonthDayRegex.test(cleanedName)) {
// 找到第一个日期模式并保留它
const dateMatch = cleanedName.match(/(20\d{2}\.\d{1,2}\.\d{1,2})/);
if (dateMatch) {
const datePart = dateMatch[1];
// 提取日期后的所有内容
const afterDate = cleanedName.substring(dateMatch.index + datePart.length);
// 如果日期后跟着数字(可能是时间戳),只保留日期部分
if (/^\d{6,}/.test(afterDate)) {
cleanedName = cleanedName.substring(0, dateMatch.index + datePart.length);
}
}
}
// 方法3:简单的字符串处理(针对你的具体案例)
if (cleanedName.includes('2025.8.18')) {
// 找到 "2025.8.18" 的位置
const startIndex = cleanedName.indexOf('2025.8.18');
if (startIndex !== -1) {
// 只保留第一个 "2025.8.18" 和之前的内容
cleanedName = cleanedName.substring(0, startIndex + '2025.8.18'.length);
}
}
// 清理多余的分隔符,但保留点号作为版本号的一部分
// 只清理末尾可能多余的符号
cleanedName = cleanedName.replace(/[._\-]+$/g, '');
// 确保文件名不为空
if (!cleanedName) {
cleanedName = `文件${index + 1}`;
}
// 重新组合文件名和扩展名
const finalFileName = cleanedName + extension;
return {
name: finalFileName,
url: url
};
});
} catch (error) {
console.warn('文件转换失败:', {
input: fileInput,
error: error.message,
stack: error.stack
});
return defaultResult;
}
}
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