by-crm/frontend/src/utils/crypto.ts
andy fd89c31640 feat(frontend): 为前端添加完整移动端响应式适配
- 新增响应式工具函数与全局移动端样式,统一适配≤768px屏幕
- 添加移动端底部导航组件,替代桌面端侧边栏菜单
- 为经销商、客户、报备列表页新增移动端卡片视图替换表格布局
- 调整所有页面的表单、弹窗与布局适配移动端尺寸
- 优化移动端viewport配置,适配全面屏安全区域
- 修复密码哈希工具,在非安全上下文下回退使用js-sha256库
- 更新依赖包,新增@vueuse/core与js-sha256
2026-08-03 15:35:45 +08:00

63 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 密码加密工具SHA-256 → 小写 hex
*
* 安全上下文HTTPS 或 localhost下使用原生 Web Crypto API
* 非安全上下文HTTP + 局域网/IP 访问,此时 crypto.subtle 为 undefined
* 下回退到纯 JS 实现 js-sha256保证产物一致登录不再卡死。
* 两条路径对同一字符串产出的 SHA-256 小写 hex 完全相同。
*/
import { sha256 } from 'js-sha256'
/** 当前环境是否可用原生 Web Crypto即处于安全上下文 */
function hasSubtleCrypto(): boolean {
return typeof crypto !== 'undefined' && typeof crypto.subtle?.digest === 'function'
}
/** 原生 Web Crypto SHA-256 → 小写 hex */
async function subtleSha256Hex(input: string): Promise<string> {
const data = new TextEncoder().encode(input)
const hashBuffer = await crypto.subtle.digest('SHA-256', data)
return Array.from(new Uint8Array(hashBuffer))
.map((b) => b.toString(16).padStart(2, '0'))
.join('')
}
/** 统一入口:优先原生,回退纯 JS */
async function sha256Hex(input: string): Promise<string> {
if (hasSubtleCrypto()) {
return subtleSha256Hex(input)
}
return sha256(input)
}
/**
* 使用 SHA-256 算法哈希密码
* @param password 明文密码
* @returns 哈希后的十六进制字符串(小写)
*/
export async function hashPassword(password: string): Promise<string> {
if (!password) return ''
try {
return await sha256Hex(password)
} catch (error) {
console.error('密码哈希失败:', error)
throw new Error('密码加密失败')
}
}
/**
* 简单的加盐哈希(可选,用于增强安全性)
* @param password 明文密码
* @param salt 盐值
* @returns 哈希后的十六进制字符串(小写)
*/
export async function hashPasswordWithSalt(password: string, salt: string): Promise<string> {
if (!password) return ''
try {
return await sha256Hex(password + salt)
} catch (error) {
console.error('密码哈希失败:', error)
throw new Error('密码加密失败')
}
}