npm package: @ruan-feiyang/front-end-utils
Description: 前端常用工具库 - 集成浏览器判断、字符串处理、日期处理、对象处理、验证函数等常用工具
Latest version: 1.0.3

# @ruan-feiyang/front-end-utils

前端常用工具库 - 集成浏览器判断、字符串处理、日期处理、对象处理、验证函数等常用工具。

## 安装

```bash
npm install @ruan-feiyang/front-end-utils
```

## 使用方法

### ES6 模块导入

```typescript
// 方式1：按需导入特定模块
import { browser, string, date, validate, func, storage } from '@ruan-feiyang/front-end-utils';

// 方式2：导入所有模块（默认导出）
import utils from '@ruan-feiyang/front-end-utils';
// 使用示例：utils.browser.isChrome()

// 方式3：直接导入特定工具
import { isChrome, isMobile } from '@ruan-feiyang/front-end-utils/browser';
import { format, fromNow } from '@ruan-feiyang/front-end-utils/date';
import { trim, capitalize } from '@ruan-feiyang/front-end-utils/string';
```

### CommonJS 模块导入

```javascript
// 方式1：导入所有模块
const utils = require('@ruan-feiyang/front-end-utils');
// 使用示例：utils.browser.isChrome()

// 方式2：导入特定模块
const { browser, string, date } = require('@ruan-feiyang/front-end-utils');
```

### 浏览器直接使用（UMD）

```html
<script src="https://unpkg.com/@ruan-feiyang/front-end-utils/dist/index.umd.js"></script>
<script>
  // 全局变量 window.frontEndUtils
  console.log(window.frontEndUtils.browser.isChrome());
  console.log(window.frontEndUtils.string.trim('  hello  '));
</script>
```

## 工具模块

### browser - 浏览器判断

```typescript
import { browser } from '@ruan-feiyang/front-end-utils';
// 或直接导入：import { isChrome, isMobile } from '@ruan-feiyang/front-end-utils/browser';

browser.isChrome()           // 判断是否为 Chrome 浏览器
browser.isFirefox()          // 判断是否为 Firefox 浏览器
browser.isSafari()           // 判断是否为 Safari 浏览器
browser.isEdge()             // 判断是否为 Edge 浏览器
browser.isIE()               // 判断是否为 IE 浏览器
browser.isMobile()           // 判断是否为移动端
browser.isWechat()           // 判断是否为微信浏览器
browser.isIOS()              // 判断是否为 iOS
browser.isAndroid()          // 判断是否为 Android
browser.getBrowserName()     // 获取浏览器名称: 'Chrome', 'Firefox', 'Safari', 'Edge', 'IE', 'Unknown'
browser.getBrowserVersion()  // 获取浏览器版本号

// 示例
if (browser.isChrome()) {
  console.log('您正在使用 Chrome 浏览器');
}
if (browser.isMobile()) {
  console.log('移动端设备');
}
```

### string - 字符串处理

```typescript
import { string } from '@ruan-feiyang/front-end-utils';
// 或直接导入：import { trim, capitalize } from '@ruan-feiyang/front-end-utils/string';

// 基本处理
string.trim('  hello  ')                      // 去除两端空白: 'hello'
string.trimAll('a  b   c')                    // 去除所有空白: 'abc'
string.escapeHtml('<div>test</div>')          // 转义 HTML: '&lt;div&gt;test&lt;/div&gt;'
string.unescapeHtml('&lt;div&gt;test&lt;/div&gt;') // 反转义 HTML: '<div>test</div>'

// 格式转换
string.capitalize('hello world')              // 首字母大写: 'Hello world'
string.camelCase('hello-world')               // 驼峰命名: 'helloWorld'
string.camelCase('hello_world test')          // 驼峰命名: 'helloWorldTest'
string.snakeCase('helloWorld')                // 下划线命名: 'hello_world'
string.kebabCase('helloWorld')                // 中划线命名: 'hello-world'

// 截断与处理
string.truncate('这是一段很长的文本需要截断', 10) // 截断: '这是一段很长...'
string.truncate('Short text', 20)             // 不截断: 'Short text'

// 脱敏处理
string.hideMobile('13812345678')              // 隐藏手机号: '138****5678'
string.maskMobile('13812345678')              // 默认中间脱敏: '138****5678'
string.maskMobile('13812345678', { mode: 'prefix' })     // 前置可见: '*******5678'
string.maskMobile('13812345678', { mode: 'suffix' })     // 后置可见: '138*******'
string.maskMobile('13812345678', { mode: 'all' })        // 全部脱敏: '***********'
string.maskMobile('13812345678', { mode: 'middle', visiblePrefix: 4, visibleSuffix: 3 }) // 自定义可见位数: '1381***678'
string.hideIdCard('110101199001011234')      // 隐藏身份证: '110101********1234'

// 示例
const userMobile = '13812345678';
console.log(`用户手机号：${string.hideMobile(userMobile)}`); // 用户手机号：138****5678

const htmlContent = '<script>alert("xss")</script>';
const safeContent = string.escapeHtml(htmlContent); // &lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;
```

### date - 日期处理

```typescript
import { date } from '@ruan-feiyang/front-end-utils';
// 或直接导入：import { format, fromNow } from '@ruan-feiyang/front-end-utils/date';

// 日期格式化
date.format(new Date())                       // 默认格式: '2024-01-01 10:30:00'
date.format(new Date(), 'YYYY/MM/DD')         // 自定义格式: '2024/01/01'
date.format(new Date(), 'YYYY年MM月DD日 HH:mm') // 中文格式: '2024年01月01日 10:30'
date.format(1700000000000, 'YYYY-MM-DD')      // 时间戳格式化: '2023-11-15'

// 相对时间
date.fromNow(Date.now() - 3600000)            // '1小时前'
date.fromNow(Date.now() - 86400000)           // '1天前'
date.fromNow(Date.now() - 3000)               // '刚刚'

// 日期范围
date.getWeekStart()                           // 获取本周开始日期（周一）
date.getWeekStart(new Date('2024-01-15'))     // 获取指定日期所在周的开始日期
date.getMonthStart()                          // 获取本月开始日期
date.getMonthStart(new Date('2024-06-15'))    // 获取指定日期所在月的开始日期

// 日期比较
date.isSameDay(new Date('2024-01-01'), new Date('2024-01-01 14:30')) // true
date.isSameDay(new Date('2024-01-01'), new Date('2024-01-02'))        // false

// 示例
const now = new Date();
console.log(`当前时间：${date.format(now)}`);
console.log(`发布时间：${date.fromNow(now.getTime() - 7200000)}`); // 2小时前

const orderDate = new Date('2024-01-15 14:30:00');
if (date.isSameDay(orderDate, new Date())) {
  console.log('这是今天的订单');
}
```

### object - 对象处理

```typescript
import { object } from '@ruan-feiyang/front-end-utils';
// 或直接导入：import { deepClone, merge } from '@ruan-feiyang/front-end-utils/object';

// 深拷贝
const original = { a: 1, b: { c: 2 }, d: new Date() };
const cloned = object.deepClone(original);   // 完全独立的副本
console.log(cloned === original);           // false
console.log(cloned.b === original.b);       // false

// 合并对象
const base = { name: '张三', age: 25 };
const updated = object.merge(base, { age: 26, city: '北京' });
console.log(updated);                       // { name: '张三', age: 26, city: '北京' }

// 支持多个源对象
const user = { name: '张三' };
const result = object.merge(user, { age: 25 }, { city: '北京' }, { email: 'test@example.com' });
console.log(result);                        // { name: '张三', age: 25, city: '北京', email: 'test@example.com' }

// 获取嵌套值
const data = { user: { profile: { name: '张三', age: 25 } } };
object.get(data, 'user.profile.name')       // '张三'
object.get(data, 'user.profile.email')      // undefined
object.get(data, 'user.profile.email', 'default@example.com') // 'default@example.com'
object.get(data, 'user.address.city', '未知') // '未知'

// 设置嵌套值
const obj = {};
object.set(obj, 'user.profile.name', '张三');
console.log(obj.user.profile.name);         // '张三'

// 创建嵌套结构
const config = {};
object.set(config, 'database.host', 'localhost');
object.set(config, 'database.port', 3306);
object.set(config, 'app.name', 'MyApp');
console.log(config);
// {
//   database: { host: 'localhost', port: 3306 },
//   app: { name: 'MyApp' }
// }

// 示例
const originalUser = {
  id: 1,
  name: '张三',
  profile: {
    email: 'zhangsan@example.com',
    address: {
      city: '北京'
    }
  }
};

// 安全修改
const modifiedUser = object.deepClone(originalUser);
object.set(modifiedUser, 'profile.address.city', '上海');
console.log(originalUser.profile.address.city); // '北京'（保持不变）
console.log(modifiedUser.profile.address.city); // '上海'

// 安全读取
const email = object.get(originalUser, 'profile.email', '未知邮箱');
const phone = object.get(originalUser, 'profile.phone', '未知电话');
console.log(email, phone); // 'zhangsan@example.com', '未知电话'
```

### validate - 验证函数

```typescript
import { validate } from '@ruan-feiyang/front-end-utils';
// 或直接导入：import { isMobile, isEmail } from '@ruan-feiyang/front-end-utils/validate';

// 手机号验证
validate.isMobile('13812345678')              // true
validate.isMobile('02812345678')              // false（区号格式）
validate.isMobile('1381234567')               // false（位数不足）
validate.isMobile('19812345678')              // true（198号段）

// 邮箱验证
validate.isEmail('test@example.com')          // true
validate.isEmail('test.name+tag@example.co.uk') // true
validate.isEmail('test@example')              // false（缺少域名后缀）
validate.isEmail('test example.com')          // false（缺少@符号）

// 身份证验证
validate.isIdCard('110101199001011234')       // true（18位）
validate.isIdCard('11010119900101123X')       // true（末尾X）
validate.isIdCard('110101900101123')          // true（15位）
validate.isIdCard('11010119900101123')        // false（17位）

// URL 验证
validate.isUrl('https://example.com')         // true
validate.isUrl('http://www.example.com/path') // true
validate.isUrl('example.com')                 // true（自动补全协议）
validate.isUrl('ftp://example.com')           // false（仅支持 http/https）

// IP 地址验证
validate.isIPv4('192.168.1.1')                // true
validate.isIPv4('255.255.255.255')            // true
validate.isIPv4('192.168.1.256')              // false（超出范围）
validate.isIPv4('192.168.1')                  // false（格式错误）

// 中文名验证
validate.isChineseName('张三')                // true
validate.isChineseName('张三丰')              // true
validate.isChineseName('张')                  // false（太短）
validate.isChineseName('张三张三张三张三张') // false（太长）
validate.isChineseName('John')                // false（非中文）

// 密码强度验证
validate.checkPasswordStrength('123456')       // 'weak'（纯数字）
validate.checkPasswordStrength('abcdef')       // 'weak'（纯字母）
validate.checkPasswordStrength('Abc123')       // 'medium'（字母+数字，长度6）
validate.checkPasswordStrength('Abc123!')      // 'strong'（字母+数字+特殊字符，长度7）
validate.checkPasswordStrength('Abcdefg123!@#') // 'strong'（混合字符，长度12）

// 示例 - 表单验证
function validateUserForm(formData) {
  const errors = {};
  
  if (!formData.name || !validate.isChineseName(formData.name)) {
    errors.name = '请输入2-10位中文姓名';
  }
  
  if (!formData.mobile || !validate.isMobile(formData.mobile)) {
    errors.mobile = '请输入有效的手机号';
  }
  
  if (!formData.email || !validate.isEmail(formData.email)) {
    errors.email = '请输入有效的邮箱地址';
  }
  
  if (!formData.password) {
    errors.password = '请输入密码';
  } else {
    const strength = validate.checkPasswordStrength(formData.password);
    if (strength === 'weak') {
      errors.password = '密码强度太弱，请使用字母、数字和特殊字符组合';
    }
  }
  
  return { isValid: Object.keys(errors).length === 0, errors };
}

// 使用示例
const formData = {
  name: '张三',
  mobile: '13812345678',
  email: 'zhangsan@example.com',
  password: 'Abc123!'
};

const result = validateUserForm(formData);
console.log(result.isValid); // true
console.log(result.errors); // {}
```

### func - 函数工具

```typescript
import { func } from '@ruan-feiyang/front-end-utils';
// 或直接导入：import { debounce, throttle } from '@ruan-feiyang/front-end-utils/func';

// 防抖（debounce）
// 在事件被触发n秒后执行函数，如果在这n秒内又被触发，则重新计时
const searchInput = document.getElementById('search');
const handleSearch = (event) => {
  console.log('搜索：', event.target.value);
  // 发送搜索请求...
};

const debouncedSearch = func.debounce(handleSearch, 300);
searchInput.addEventListener('input', debouncedSearch);

// 示例：输入框实时搜索，避免频繁请求
const searchApi = (keyword) => {
  console.log(`搜索关键词: ${keyword}`);
  // fetch(`/api/search?q=${keyword}`)...
};

const debouncedSearchApi = func.debounce(searchApi, 500);
document.getElementById('search-input').addEventListener('input', (e) => {
  debouncedSearchApi(e.target.value);
});

// 节流（throttle）
// 在一个单位时间内，只能触发一次函数，如果这个单位时间内触发多次函数，只有一次生效
const handleScroll = () => {
  console.log('滚动位置：', window.scrollY);
};

const throttledScroll = func.throttle(handleScroll, 200);
window.addEventListener('scroll', throttledScroll);

// 示例：窗口resize事件
const handleResize = () => {
  console.log('窗口大小：', window.innerWidth, window.innerHeight);
  // 更新布局...
};

const throttledResize = func.throttle(handleResize, 100);
window.addEventListener('resize', throttledResize);

// 柯里化（curry）
// 将多参数的函数转换成一系列单参数函数
const add = (a, b, c) => a + b + c;
const curriedAdd = func.curry(add);

// 使用方式
const add5 = (b, c) => curriedAdd([5, b, c]);
console.log(add5(3, 4)); // 12

// 或直接调用
console.log(curriedAdd([1, 2, 3])); // 6

// 一次性函数（once）
// 确保函数只执行一次，后续调用返回undefined或第一次的结果
const initializeApp = () => {
  console.log('应用初始化完成');
  return 'initialized';
};

const initializeOnce = func.once(initializeApp);

console.log(initializeOnce()); // '应用初始化完成'，返回 'initialized'
console.log(initializeOnce()); // undefined（不再执行）
console.log(initializeOnce()); // undefined

// 示例：支付按钮防重复点击
const handlePayment = () => {
  console.log('支付请求发送...');
  // 发送支付请求...
  return 'payment_sent';
};

const safePayment = func.once(handlePayment);

document.getElementById('pay-button').addEventListener('click', () => {
  const result = safePayment();
  if (result) {
    console.log('支付处理中...');
  } else {
    console.log('请勿重复点击');
  }
});

// 组合使用示例
class SearchComponent {
  constructor() {
    this.search = func.debounce(this._performSearch.bind(this), 300);
    this.initialize = func.once(this._initialize.bind(this));
  }
  
  _performSearch(keyword) {
    console.log(`执行搜索: ${keyword}`);
    // 实际搜索逻辑
  }
  
  _initialize() {
    console.log('组件初始化');
    // 初始化逻辑
  }
  
  onInput(keyword) {
    this.initialize(); // 只初始化一次
    this.search(keyword); // 防抖搜索
  }
}

// 使用
const searchComponent = new SearchComponent();
searchComponent.onInput('react'); // 初始化 + 防抖搜索
searchComponent.onInput('react hooks'); // 只触发防抖搜索
```

### number - 数字处理

```typescript
number.formatThousands(1234567)               // 千分位: '1,234,567'
number.padZero(5, 2)                          // 补零: '05'
number.round(3.14159, 2)                      // 四舍五入: 3.14
number.randomInt(1, 100)                     // 随机整数
number.toChinese(123)                        // 数字转中文: '一百二十三'
```

### array - 数组处理

```typescript
array.unique([1, 2, 2, 3])                    // 去重: [1, 2, 3]
array.shuffle([1, 2, 3])                     // 乱序
array.groupBy(items, 'category')              // 分组
array.sortBy(items, 'age', 'asc')             // 排序
array.flat([1, [2, 3]], 1)                   // 扁平化
array.difference([1, 2, 3], [2])             // 差集: [1, 3]
array.intersection([1, 2, 3], [2, 3])         // 交集: [2, 3]
```

### storage - localStorage

```typescript
import { storage } from '@ruan-feiyang/front-end-utils';
// 或直接导入：import { set, get } from '@ruan-feiyang/front-end-utils/storage';

// 设置数据（自动 JSON 序列化）
storage.set('user', { name: '张三', age: 25 });
storage.set('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');
storage.set('settings', { theme: 'dark', language: 'zh-CN' });

// 获取数据（自动 JSON 反序列化）
const user = storage.get('user');           // { name: '张三', age: 25 }
const token = storage.get('token');         // 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
const settings = storage.get('settings');   // { theme: 'dark', language: 'zh-CN' }

// 获取不存在的键（返回默认值）
const cart = storage.get('cart', []);       // []（默认值）
const history = storage.get('history');     // null（无默认值）

// 检查是否存在
if (storage.has('user')) {
  console.log('用户信息已保存');
}

// 删除数据
storage.remove('token');                    // 删除 token
storage.remove('tempData');                 // 删除临时数据

// 清空所有数据
// storage.clear();                         // 谨慎使用，会清空所有 localStorage

// 示例：用户会话管理
class UserSession {
  private static readonly USER_KEY = 'user_session';
  private static readonly TOKEN_KEY = 'auth_token';
  
  static login(userData: { id: number; name: string; email: string }, token: string) {
    storage.set(this.USER_KEY, userData);
    storage.set(this.TOKEN_KEY, token);
  }
  
  static logout() {
    storage.remove(this.USER_KEY);
    storage.remove(this.TOKEN_KEY);
  }
  
  static getCurrentUser() {
    return storage.get<{ id: number; name: string; email: string }>(this.USER_KEY);
  }
  
  static getToken() {
    return storage.get<string>(this.TOKEN_KEY);
  }
  
  static isLoggedIn() {
    return storage.has(this.USER_KEY) && storage.has(this.TOKEN_KEY);
  }
}

// 使用示例
UserSession.login(
  { id: 1, name: '张三', email: 'zhangsan@example.com' },
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
);

console.log(UserSession.isLoggedIn());      // true
console.log(UserSession.getCurrentUser());  // { id: 1, name: '张三', email: 'zhangsan@example.com' }

UserSession.logout();
console.log(UserSession.isLoggedIn());      // false

// 示例：购物车管理
class ShoppingCart {
  private static readonly CART_KEY = 'shopping_cart';
  
  static addItem(item: { id: number; name: string; price: number; quantity: number }) {
    const cart = storage.get<Array<{ id: number; name: string; price: number; quantity: number }>>(this.CART_KEY, []);
    const existingItem = cart.find(i => i.id === item.id);
    
    if (existingItem) {
      existingItem.quantity += item.quantity;
    } else {
      cart.push(item);
    }
    
    storage.set(this.CART_KEY, cart);
    return cart;
  }
  
  static removeItem(itemId: number) {
    const cart = storage.get<Array<{ id: number; name: string; price: number; quantity: number }>>(this.CART_KEY, []);
    const filteredCart = cart.filter(item => item.id !== itemId);
    storage.set(this.CART_KEY, filteredCart);
    return filteredCart;
  }
  
  static getCart() {
    return storage.get<Array<{ id: number; name: string; price: number; quantity: number }>>(this.CART_KEY, []);
  }
  
  static clearCart() {
    storage.set(this.CART_KEY, []);
  }
  
  static getTotal() {
    const cart = this.getCart();
    return cart.reduce((total, item) => total + (item.price * item.quantity), 0);
  }
}

// 使用示例
ShoppingCart.addItem({ id: 1, name: '商品A', price: 100, quantity: 2 });
ShoppingCart.addItem({ id: 2, name: '商品B', price: 200, quantity: 1 });

console.log(ShoppingCart.getCart());
// [
//   { id: 1, name: '商品A', price: 100, quantity: 2 },
//   { id: 2, name: '商品B', price: 200, quantity: 1 }
// ]

console.log(`总价：${ShoppingCart.getTotal()}`); // 总价：400

ShoppingCart.removeItem(1);
console.log(ShoppingCart.getCart()); // [{ id: 2, name: '商品B', price: 200, quantity: 1 }]
```

### sessionStorage - 会话存储

```typescript
sessionStorage.set('key', value)           // 设置
sessionStorage.get('key')                    // 获取
sessionStorage.remove('key')                // 删除
sessionStorage.clear()                      // 清空
sessionStorage.has('key')                   // 是否存在
```

### cache - 内存缓存

```typescript
cache.set('key', value, ttl)                 // 设置缓存，ttl=秒数
cache.get('key')                             // 获取
cache.remove('key')                         // 删除
cache.clear()                               // 清空
cache.has('key')                             // 是否存在
cache.keys()                               // 所有缓存键
cache.cleanup()                             // 清理过期缓存
```

### withCache - 带缓存的异步函数

```typescript
const data = await withCache('key', () => fetchApi(), 300)
// 自动缓存结果，避免重复请求
```

### cacheBatch - 批量缓存操作

```typescript
cacheBatch.getMultiple(['key1', 'key2'])   // 批量获取
cacheBatch.setMultiple({ k1: v1, k2: v2 })  // 批量设置
cacheBatch.removeMultiple(['key1'])         // 批量删除
```

### cookie

```typescript
cookie.set('name', 'value', 7)              // 设置
cookie.get('name')                         // 获取
cookie.remove('name')                      // 删除
```

### 其他工具

```typescript
copyToClipboard('text')                      // 复制到剪贴板
downloadFile('content', 'file.txt')          // 下载文件
formatMoney(1234.56)                        // 金额格式化: '¥1,234.56'
formatFileSize(1024 * 1024)                 // 文件大小: '1.00 MB'
getFileExtension('file.txt')                 // 获取扩展名: 'txt'
generateUUID()                              // 生成 UUID
sleep(1000)                                // 等待指定毫秒
```

### url - URL 工具

```typescript
import { url } from '@ruan-feiyang/front-end-utils';
// 或直接导入：import { encode, decode } from '@ruan-feiyang/front-end-utils/url';

// URL 编码
url.encode('测试 & 数据')                   // 编码: '%E6%B5%8B%E8%AF%95%20%26%20%E6%95%B0%E6%8D%AE'

// URL 解码
url.decode('%E6%B5%8B%E8%AF%95')           // 解码: '测试'

// 解析 URL 参数
url.parseParams('https://example.com?name=张三&age=25') // { name: '张三', age: '25' }

// 构建 URL 参数
url.buildParams({ name: '张三', age: '25' }) // 'name=%E5%BC%A0%E4%B8%89&age=25'

// 获取 URL 中的指定参数
url.getParam('name', 'https://example.com?name=张三&age=25') // '张三'

// 从 URL 中移除指定参数
url.removeParams('https://example.com?name=张三&age=25', ['age']) // 'https://example.com?name=张三'

// 示例：处理 URL 参数
const currentUrl = window.location.href;
const params = url.parseParams(currentUrl);
console.log('当前页面参数:', params);

// 构建带参数的 URL
const baseUrl = 'https://api.example.com';
const queryParams = { page: '1', limit: '10', keyword: '测试' };
const fullUrl = `${baseUrl}?${url.buildParams(queryParams)}`;
console.log('完整 URL:', fullUrl);
```

### page - 页面工具

```typescript
page.scrollToTop()                          // 滚动到顶部
page.goBack()                             // 回到上一页
page.reload()                            // 刷新页面
page.getQueryParam('id')                  // 获取 URL 参数
page.getAllQueryParams()                  // 获取所有 URL 参数
page.getHash()                           // 获取锚点
```

### device - 设备工具

```typescript
import { device } from '@ruan-feiyang/front-end-utils';
// 或直接导入：import { getNetworkType, isTouchDevice } from '@ruan-feiyang/front-end-utils/device';

// 获取网络类型
device.getNetworkType()                    // 'wifi', '4g', '3g', '2g', 'unknown'
// 注意：需要浏览器支持 navigator.connection

// 检测触摸设备
device.isTouchDevice()                     // true（支持触屏）/ false

// 获取设备像素比
device.getDevicePixelRatio()               // 1, 1.5, 2, 3（Retina 显示）

// 获取屏幕尺寸
device.getScreenWidth()                    // 屏幕宽度（像素）
device.getScreenHeight()                   // 屏幕高度（像素）

// 获取窗口尺寸
device.getWindowWidth()                    // 可视区域宽度（像素）
device.getWindowHeight()                   // 可视区域高度（像素）

// 示例：响应式设计
function checkDeviceCapabilities() {
  const capabilities = {
    isMobile: device.isTouchDevice() && device.getScreenWidth() < 768,
    isTablet: device.isTouchDevice() && device.getScreenWidth() >= 768 && device.getScreenWidth() < 1024,
    isDesktop: !device.isTouchDevice() || device.getScreenWidth() >= 1024,
    pixelRatio: device.getDevicePixelRatio(),
    networkType: device.getNetworkType(),
    screenSize: {
      width: device.getScreenWidth(),
      height: device.getScreenHeight()
    },
    windowSize: {
      width: device.getWindowWidth(),
      height: device.getWindowHeight()
    }
  };
  
  return capabilities;
}

// 使用示例
const caps = checkDeviceCapabilities();
if (caps.isMobile) {
  console.log('移动端设备，启用移动端优化');
  // 加载移动端组件...
} else if (caps.isTablet) {
  console.log('平板设备，启用平板布局');
  // 加载平板组件...
} else {
  console.log('桌面端设备，启用完整功能');
  // 加载桌面端组件...
}

// 根据像素比优化图片
if (caps.pixelRatio >= 2) {
  console.log('高分辨率屏幕，加载高清图片');
  // img.src = 'image@2x.png';
} else {
  console.log('普通分辨率屏幕，加载普通图片');
  // img.src = 'image.png';
}

// 根据网络类型优化加载策略
if (caps.networkType === '4g' || caps.networkType === 'wifi') {
  console.log('高速网络，加载高质量资源');
  // 加载高清视频、大图等
} else {
  console.log('低速网络，加载轻量资源');
  // 加载低质量图片、压缩资源等
}
```

## 更多工具模块

除了上述主要模块外，库还包含以下实用工具：

### 数组处理 (array)
- `array.unique()` - 数组去重
- `array.shuffle()` - 数组乱序
- `array.groupBy()` - 按属性分组
- `array.sortBy()` - 按属性排序
- `array.flat()` - 数组扁平化
- `array.difference()` - 数组差集
- `array.intersection()` - 数组交集

### 数字处理 (number)
- `number.formatThousands()` - 千分位格式化
- `number.padZero()` - 数字补零
- `number.round()` - 四舍五入
- `number.randomInt()` - 随机整数
- `number.toChinese()` - 数字转中文

### Cookie 操作 (cookie)
- `cookie.set()` - 设置 Cookie
- `cookie.get()` - 获取 Cookie
- `cookie.remove()` - 删除 Cookie

### 缓存管理 (cache)
- `cache.set()` - 设置内存缓存
- `cache.get()` - 获取缓存
- `cache.remove()` - 删除缓存
- `cache.clear()` - 清空缓存
- `cache.has()` - 检查缓存是否存在
- `cache.keys()` - 获取所有缓存键
- `cache.cleanup()` - 清理过期缓存
- `withCache()` - 带缓存的异步函数
- `cacheBatch` - 批量缓存操作

### 页面工具 (page)
- `page.scrollToTop()` - 滚动到顶部
- `page.goBack()` - 回到上一页
- `page.reload()` - 刷新页面
- `page.getQueryParam()` - 获取 URL 参数
- `page.getAllQueryParams()` - 获取所有 URL 参数
- `page.getHash()` - 获取锚点

### URL 工具 (url)
- `url.encode()` - URL 编码
- `url.decode()` - URL 解码
- `url.parseParams()` - 解析 URL 参数
- `url.buildParams()` - 构建 URL 参数
- `url.getParam()` - 获取 URL 中的指定参数
- `url.removeParams()` - 从 URL 中移除指定参数

### 杂项工具 (misc)
- `copyToClipboard()` - 复制到剪贴板
- `downloadFile()` - 下载文件
- `formatMoney()` - 金额格式化
- `formatFileSize()` - 文件大小格式化
- `getFileExtension()` - 获取文件扩展名
- `generateUUID()` - 生成 UUID
- `sleep()` - 等待指定毫秒

## TypeScript 支持

本库完全使用 TypeScript 编写，提供完整的类型定义：

```typescript
import { browser, string, date } from '@ruan-feiyang/front-end-utils';

// 类型安全的使用
const isChrome: boolean = browser.isChrome();
const trimmed: string = string.trim('  hello  ');
const formattedDate: string = date.format(new Date());

// 泛型支持
interface User {
  id: number;
  name: string;
  email: string;
}

const user: User = { id: 1, name: '张三', email: 'test@example.com' };
const clonedUser: User = object.deepClone(user);
```

## 开发指南

### 本地开发

```bash
# 克隆仓库
git clone <repository-url>
cd front_end_utils

# 安装依赖
npm install

# 开发模式（监听文件变化）
npm run dev

# 构建生产版本
npm run build

# 运行测试
npm test
```

### 项目结构

```
src/
├── index.ts          # 主入口文件，导出所有模块
├── browser.ts        # 浏览器判断工具
├── string.ts         # 字符串处理工具
├── date.ts           # 日期处理工具
├── object.ts         # 对象处理工具
├── validate.ts       # 验证函数工具
├── func.ts           # 函数工具
├── number.ts         # 数字处理工具
├── array.ts          # 数组处理工具
├── storage.ts        # localStorage 工具
├── sessionStorage.ts # sessionStorage 工具
├── cache.ts          # 缓存管理工具
├── cookie.ts         # Cookie 操作工具
├── misc.ts           # 杂项工具
├── page.ts           # 页面工具
├── device.ts         # 设备工具
└── url.ts            # URL 工具
```

### 添加新工具

1. 在 `src/` 目录下创建新的模块文件
2. 实现工具函数并导出
3. 在 `src/index.ts` 中导出新模块
4. 运行测试确保功能正常
5. 更新 README.md 文档

## 构建与发布

### 构建项目

```bash
npm run build
```

构建产物位于 `dist/` 目录，包含：
- CommonJS 格式 (`.js`)
- ES Module 格式 (`.esm.js`)
- TypeScript 类型定义 (`.d.ts`)

### 发布到 npm

```bash
# 登录 npm
npm login

# 更新版本号
npm version patch  # 或 minor、major

# 发布
npm publish --access public
```

## 测试

项目使用 Jest 进行单元测试：

```bash
# 运行所有测试
npm test

# 运行特定测试文件
npm test -- string.test.ts

# 查看测试覆盖率
npm test -- --coverage
```

## 贡献指南

1. Fork 项目仓库
2. 创建功能分支 (`git checkout -b feature/amazing-feature`)
3. 提交更改 (`git commit -m 'Add some amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 创建 Pull Request

## 许可证

MIT License

## 联系方式

- 项目地址：[GitHub Repository](https://github.com/your-username/front-end-utils)
- 问题反馈：[GitHub Issues](https://github.com/your-username/front-end-utils/issues)
- npm 包：[@ruan-feiyang/front-end-utils](https://www.npmjs.com/package/@ruan-feiyang/front-end-utils)