Skip to content

Commit

Permalink
Merge branch 'main' of github.com:chenbimo/yidash
Browse files Browse the repository at this point in the history
  • Loading branch information
chenbimo committed Aug 5, 2024
2 parents e8600c3 + afdd1a0 commit ac2d685
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 0 deletions.
38 changes: 38 additions & 0 deletions lib/browser/openWindow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* 在当前页面打开新窗口页
* @author 王勇 <https://github.com/wangyong1997>
* @category browser
* @alias yd_browser_openWindow
* @param {string} url 打开的网页地址
* @param {string} title 打开的网页标题
* @param {number} width 打开网页的宽度
* @param {number} height 打开网页的高度
* @returns {Window | null} 新打开的窗口对象,或在失败时返回 null
*/

export default (url, title, width, height) => {
// 获取屏幕位置和尺寸
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top

const screenWidth = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width
const screenHeight = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height

// 计算窗口位置以居中显示
const left = ((screenWidth / 2) - (width / 2)) + dualScreenLeft
const top = ((screenHeight / 2) - (height / 2)) + dualScreenTop

// 打开新窗口
const newWindow = window.open(
url,
title,
`toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=${width}, height=${height}, top=${top}, left=${left}`
);

// 如果可能,将焦点放在新窗口上
if (newWindow && typeof newWindow.focus === 'function') {
newWindow.focus();
}

return newWindow;
}
65 changes: 65 additions & 0 deletions lib/browser/scrollTo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Quadratic ease-in-out function for smooth scrolling
const easeInOutQuad = (t, b, c, d) => {
t /= d / 2;
if (t < 1) {
return c / 2 * t * t + b;
}
t--;
return -c / 2 * (t * (t - 2) - 1) + b;
};

// RequestAnimationFrame polyfill for smooth animations
const requestAnimFrame = (() => {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback) { window.setTimeout(callback, 1000 / 60); };
})();

/**
* Move the scroll position to a specific amount
* @param {number} amount - The amount to scroll
*/
function move(amount) {
document.documentElement.scrollTop = amount;
document.body.parentNode.scrollTop = amount;
document.body.scrollTop = amount;
}

/**
* Get the current scroll position
* @returns {number} - The current scroll position
*/
function position() {
return document.documentElement.scrollTop ||
document.body.parentNode.scrollTop ||
document.body.scrollTop;
}

/**
* 平滑滚动到特定位置
* @author 王勇 <https://github.com/wangyong1997>
* @category browser
* @alias yd_browser_scrollTo
* @param {number} to - 目标滚动位置
* @param {number} [duration=500] - 滚动动画的持续时间,以毫秒为单位
* @param {Function} [callback] - 在滚动动画完成后执行的回调函数
*/
export default (to, duration = 500, callback) => {
const start = position();
const change = to - start;
const increment = 20;
let currentTime = 0;
function animateScroll() {
currentTime += increment;
const val = easeInOutQuad(currentTime, start, change, duration);
move(val);
if (currentTime < duration) {
requestAnimFrame(animateScroll);
} else if (typeof callback === 'function') {
callback();
}
}

animateScroll();
}
33 changes: 33 additions & 0 deletions lib/datetime/computeAge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { parseISO, isValid, differenceInYears, isBefore } from 'date-fns';

/**
* 计算年龄
*
* @author 卞雪瑞 <[email protected]>
* @category 时间操作
* @alias yd_compute_age
* @param {String} birthday - 生日日期字符串
* @summary 根据给的生日计算出用户的年龄
* @returns {Number} - 返回计算出的年龄,如果未提供生日则返回0
*/
const computeAge = (birthday) => {
if (birthday) {
const _birthday = parseISO(birthday);

if (!isValid(_birthday)) {
return 0;
}

const cur = new Date();
let age = differenceInYears(cur, _birthday);

if (isBefore(cur, new Date(cur.getFullYear(), _birthday.getMonth(), _birthday.getDate()))) {
age--;
}

return age;
}
return 0;
};

export default computeAge;
36 changes: 36 additions & 0 deletions lib/datetime/computeAge.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { describe, test, expect } from 'vitest';
import { format, parseISO, getYear, subMonths } from 'date-fns';
import dy_compute_age from './computeAge'; // 确保路径正确

describe('dy_compute_age', () => {
test('正确计算年龄', () => {
const birthday = '1990-01-01'; // 例如,出生日期为 1990 年 1 月 1 日
const expectedAge = new Date().getFullYear() - 1990; // 计算预期的年龄
const age = dy_compute_age(birthday);
expect(age).toBe(expectedAge);
});

test('计算同一天出生的年龄应为 0', () => {
const today = format(new Date(), 'yyyy-MM-dd');
const age = dy_compute_age(today);
expect(age).toBe(0);
});

test('边界情况:出生日期在今年的某一天', () => {
const birthday = format(subMonths(new Date(), 5), 'yyyy-MM-dd'); // 例如,5 个月前
const expectedAge = getYear(new Date()) - getYear(parseISO(birthday));
const age = dy_compute_age(birthday);
expect(age).toBe(expectedAge);
});

test('无效日期应返回 0', () => {
const invalidDate = 'not-a-date';
const age = dy_compute_age(invalidDate);
expect(age).toBe(0);
});

test('未提供出生日期应返回 0', () => {
const age = dy_compute_age();
expect(age).toBe(0);
});
});
29 changes: 29 additions & 0 deletions lib/datetime/dateRange.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { add, isBefore } from 'date-fns';

/**
* 返回一个时间范围
* @category 时间操作
* @alias yd_date_range
* @param {number} year - 需要增加的年数,默认为0
* @param {number} month - 需要增加的月数,默认为0
* @param {number} day - 需要增加的天数,默认为0
* @param {number} hour - 需要增加的小时数,默认为0
* @param {number} minute - 需要增加的分钟数,默认为0
* @param {number} second - 需要增加的秒数,默认为0
* @summary 生成一个时间范围数组,该数组包含当前时间和目标时间
* 如果目标时间在当前时间之后,则返回 [当前时间, 目标时间] 的数组
* 如果目标时间在当前时间之前或相同,则返回 [目标时间, 当前时间] 的数组
* @returns {Array} 返回一个包含两个Date对象的数组,分别代表开始时间和结束时间
*/

const dateRange = (year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0) => {
const now = new Date();
const targetDate = add(now, { years: year, months: month, days: day, hours: hour, minutes: minute, seconds: second });

if (isBefore(now, targetDate)) {
return [now, targetDate];
}
return [targetDate, now];
};

export default dateRange;
47 changes: 47 additions & 0 deletions lib/datetime/dateRange.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { describe, test, expect } from 'vitest';
import { add, isEqual, isBefore, startOfSecond } from 'date-fns';
import yd_date_range from './dateRange';

describe('yd_date_range', () => {
test('默认情况下返回当前时间范围', () => {
const [start, end] = yd_date_range();
const now = new Date();
expect(isEqual(startOfSecond(start), startOfSecond(now))).toBe(true);
expect(isEqual(startOfSecond(end), startOfSecond(now))).toBe(true);
});

test('增加一年', () => {
const [start, end] = yd_date_range(1);
expect(end.getFullYear()).toBe(start.getFullYear() + 1);
});

test('增加一个月', () => {
const [start, end] = yd_date_range(0, 1);
expect((end.getMonth() + 12) % 12).toBe((start.getMonth() + 1) % 12);
});

test('增加一天', () => {
const [start, end] = yd_date_range(0, 0, 1);
expect(end.getDate()).toBe(start.getDate() + 1);
});

test('增加一小时', () => {
const [start, end] = yd_date_range(0, 0, 0, 1);
expect((end.getHours() + 24) % 24).toBe((start.getHours() + 1) % 24);
});

test('增加一分钟', () => {
const [start, end] = yd_date_range(0, 0, 0, 0, 1);
expect((end.getMinutes() + 60) % 60).toBe((start.getMinutes() + 1) % 60);
});

test('增加一秒钟', () => {
const [start, end] = yd_date_range(0, 0, 0, 0, 0, 1);
expect((end.getSeconds() + 60) % 60).toBe((start.getSeconds() + 1) % 60);
});

test('如果目标日期在当前日期之前,返回的顺序应调整', () => {
const [start, end] = yd_date_range(-1); // 减少一年
expect(isBefore(start, end)).toBe(true);
});
});
15 changes: 15 additions & 0 deletions lib/idCard/getSex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @description 根据身份证获取性别
* @author grantguo <https://github.com/ForeverGuo>
* @category idCard
* @alias yd_idCard_getSex
* @param { string } card 身份证号
* @return 返回性别
* @summary 根据身份证号码获取性别
* @example
* yd_idCard_getSex(card)
*/
export default (card) => {
const num = Number(card.slice(-2, -1));
return num % 2 === 0 ? '女性' : '男性';
};
11 changes: 11 additions & 0 deletions lib/idCard/getSex.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { describe, it, expect } from 'vitest';
import yd_idCard_getSex from './getSex.js';

describe('yd_idCard_getAge', () => {
it('获取性别', () => {
const sex_1 = yd_idCard_getSex('220181199608286312');
expect(sex_1).toEqual('男性');
const sex_2 = yd_idCard_getSex('42132120020509720X');
expect(sex_2).toEqual('女性');
});
});

0 comments on commit ac2d685

Please sign in to comment.