访客模块待完成

This commit is contained in:
Zy
2026-04-11 17:55:11 +08:00
parent 67a292b252
commit d957d1a039
35 changed files with 4564 additions and 95 deletions

66
src/utils/Reg.ts Normal file
View File

@@ -0,0 +1,66 @@
/**
* 验证身份证号码18位支持尾号x/X
* @param idCard 身份证号
* @return {boolean} true 符合 false 不符合
*/
export function validateIdCard(idCard: string): boolean {
// 18位身份证正则
const reg = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
return reg.test(idCard.trim());
}
/**
* 验证车牌号
* @param val 兼容新能源 + 普通车牌
* @return {boolean} true 符合 false 不符合
*/
export function isPlateNumber(val: string): boolean {
const reg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/;
return reg.test(val);
}
/**
* 验证金钱
* @param {number} val
* @return {boolean} true 符合 false 不符合
*/
export function isMoney(value: number): boolean {
const reg = /^(0|[1-9]\d*)(\.\d{1,2})?$/;
return reg.test(String(value).trim());
}
/**
* 验证姓名
* @param {string} val
* @return {boolean} true 符合 false 不符合
*/
export function isChineseName(val: string): boolean {
return /^[\u4e00-\u9fa5·]{2,16}$/.test(String(val).trim());
}
const reg = {
/** 金钱 */
money: /^(0|[1-9]\d*)(\.\d{1,2})?$/,
/** 身份证 */
idCard: /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/,
/** 车牌 */
PlateNumber: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼][A-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/,
/** 姓名 */
ChineseName: /^[\u4e00-\u9fa5·]{2,16}$/,
/** 手机号 */
phone: /^1[3-9]\d{9}$/,
/** 邮箱 */
email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
/** QQ */
qq: /^[1-9]\d{4,11}$/,
/** 微信 */
wechat: /^[a-zA-Z][a-zA-Z0-9_-]{5,19}$/
};
// 自动推导 TS 类型(最标准)
export type RegType = keyof typeof reg;
/**
* 验证姓名
* @param {string|number} value
* @param {string} regType
* @return {boolean} true 符合 false 不符合
*/
export function validator(value: string | number, regType: RegType): boolean {
return reg[regType].test(String(value));
}

View File

@@ -54,7 +54,6 @@ export function convertBuildingToTree(buildings: any[]): Tree[] {
});
buildingTree.children = unitTrees;
console.log(buildingTree);
return buildingTree;
});
}
@@ -121,17 +120,6 @@ export function getHousePathById(treeData: Tree[], houseId: number, response: Va
return path;
}
/**
* 验证身份证号码18位支持尾号x/X
* @param idCard 身份证号
* @return {boolean} true 符合 false 不符合
*/
export function validateIdCard(idCard: string): boolean {
// 18位身份证正则
const reg = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
return reg.test(idCard.trim());
}
export const houseUselist = ['普通住宅', '商业用地', '商住两用', '其他'];
// 对字符串 图片地址,处理

View File

@@ -316,3 +316,53 @@ export const removeClass = (ele: HTMLElement, cls: string) => {
export const isExternal = (path: string) => {
return /^(https?:|http?:|mailto:|tel:)/.test(path);
};
/**
* 通用:根据 projectLevel 层级字段,将扁平数组转为树形结构
* @param list 原始扁平数组
* @returns 树形结构数据children 为空则设为 null
*/
export function buildTreeByLevel<T = any>(list: T[]): T[] {
if (!list || list.length === 0) return [];
// 1. 深拷贝 + 初始化 children
const data = JSON.parse(JSON.stringify(list));
data.forEach((item: any) => (item.children = []));
const tree: any[] = [];
// 2. 根据 projectLevel 构建父子关系
data.forEach((item: any, index: number) => {
const level = Number(item.projectLevel);
// 顶级节点level = 0
if (level === 0) {
tree.push(item);
}
// 子节点:寻找上一级节点
else {
const parentLevel = level - 1;
// 向前寻找最近的父级
const parent = data
.slice(0, index)
.reverse()
.find((i: any) => Number(i.projectLevel) === parentLevel);
if (parent) parent.children.push(item);
}
});
// 3. 清理空 children没有子节点 = null表格不显示展开箭头
const cleanEmptyChildren = (nodes: any[]) => {
nodes.forEach((node) => {
if (node.children?.length === 0) {
node.children = null;
} else if (node.children) {
cleanEmptyChildren(node.children);
}
});
};
cleanEmptyChildren(tree);
return tree;
}

66
src/utils/time.ts Normal file
View File

@@ -0,0 +1,66 @@
/**
* 计算两个日期之间相差的天数
* @param date1 开始日期
* @param date2 结束日期
* @returns 相差天数(绝对值)
*/
export function diffDays(date1: string | Date, date2: string | Date): number {
const d1 = new Date(date1);
const d2 = new Date(date2);
// 转为时间戳并取绝对值
const diff = Math.abs(d1.getTime() - d2.getTime());
// 一天的毫秒数
return Math.floor(diff / (1000 * 60 * 60 * 24));
}
/**
* 格式化两个时间的差值,自动显示 年/月/天/时/分/秒
* @param startTime 开始时间Date / 时间戳 / 字符串)
* @param endTime 结束时间,默认当前时间
* @returns 如2年3个月、15天、2小时30分、50秒
*/
export function formatTimeDiff(startTime: string | number | Date, endTime: string | number | Date = new Date()): string {
const start = new Date(startTime).getTime();
const end = new Date(endTime).getTime();
// 毫秒差值(绝对值)
let diff = Math.abs(end - start);
if (diff < 1000) return '0秒';
// 单位定义
const second = 1000;
const minute = 60 * second;
const hour = 60 * minute;
const day = 24 * hour;
const month = 30 * day; // 粗略按月计算
const year = 365 * day;
// 计算
const years = Math.floor(diff / year);
diff -= years * year;
const months = Math.floor(diff / month);
diff -= months * month;
const days = Math.floor(diff / day);
diff -= days * day;
const hours = Math.floor(diff / hour);
diff -= hours * hour;
const minutes = Math.floor(diff / minute);
diff -= minutes * minute;
const seconds = Math.floor(diff / second);
// 拼接显示
const res: string[] = [];
if (years > 0) res.push(years + '年');
if (months > 0) res.push(months + '个月');
if (days > 0) res.push(days + '天');
if (hours > 0) res.push(hours + '小时');
if (minutes > 0) res.push(minutes + '分钟');
if (seconds > 0 && res.length === 0) res.push(seconds + '秒');
return res.join('');
}