feat: 登录认证 + 用户/角色/组织架构/审计日志管理页
- 新增登录页、认证 store、路由守卫(未登录跳转 + meta.permissions 校验 + 401 统一处理) - 新增 v-permission 按钮权限指令,Sidebar 按权限过滤菜单,Header 绑定真实用户+改密+退出 - 用户管理:增删改查、启停、重置密码、分配角色、组织树选择、岗位、技能标签 - 角色管理:预定义角色矩阵、权限分配、数据范围(全部/本组织及下级) - 组织架构:固定层级 公司/实验室/部门/班组(白夜班) 树形管理 + 数据权限摘要展示 - 审计日志页:操作人/类型/对象/时间段筛选 + 前后值查看 - 补齐同事模块缺失文件:api/alert.js、utils/format.js(修复构建) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+22
-40
@@ -1,60 +1,42 @@
|
||||
/**
|
||||
* 通用格式化工具(后端返回的日期为 ISO 字符串,如 "2026-08-28T10:30:00")
|
||||
* 通用格式化工具(asset 台账视图与告警页共用)
|
||||
*/
|
||||
|
||||
// 补零:5 → "05"
|
||||
const pad = n => String(n).padStart(2, '0')
|
||||
|
||||
/**
|
||||
* 格式化为日期:2026-08-28
|
||||
* @param {string|Date} value 日期/时间值
|
||||
* @returns {string} 空值返回 ''
|
||||
*/
|
||||
// 日期:YYYY-MM-DD(兼容 ISO 字符串 / Date)
|
||||
export function fmtDate(value) {
|
||||
if (!value) return ''
|
||||
if (!value) return '-'
|
||||
const d = new Date(value)
|
||||
if (isNaN(d.getTime())) return String(value).slice(0, 10)
|
||||
if (Number.isNaN(d.getTime())) return String(value)
|
||||
const pad = (n) => String(n).padStart(2, '0')
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化为日期时间:2026-08-28 10:30:00
|
||||
* @param {string|Date} value 日期/时间值
|
||||
* @returns {string} 空值返回 ''
|
||||
*/
|
||||
// 日期时间:YYYY-MM-DD HH:mm:ss
|
||||
export function fmtDateTime(value) {
|
||||
if (!value) return ''
|
||||
if (!value) return '-'
|
||||
const d = new Date(value)
|
||||
if (isNaN(d.getTime())) return String(value).replace('T', ' ').slice(0, 19)
|
||||
if (Number.isNaN(d.getTime())) return String(value)
|
||||
const pad = (n) => String(n).padStart(2, '0')
|
||||
return `${fmtDate(d)} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文件大小:1024 → "1.00 KB"
|
||||
* @param {number} bytes 字节数
|
||||
* @returns {string} 空值返回 ''
|
||||
*/
|
||||
// 文件大小(字节 → 可读单位)
|
||||
export function fmtFileSize(bytes) {
|
||||
if (bytes === null || bytes === undefined || isNaN(bytes)) return ''
|
||||
if (bytes < 1024) return `${bytes} B`
|
||||
const units = ['KB', 'MB', 'GB', 'TB']
|
||||
let size = bytes
|
||||
let i = -1
|
||||
do {
|
||||
size /= 1024
|
||||
i++
|
||||
} while (size >= 1024 && i < units.length - 1)
|
||||
return `${size.toFixed(2)} ${units[i]}`
|
||||
if (bytes == null || bytes === '' || Number.isNaN(Number(bytes))) return '-'
|
||||
const n = Number(bytes)
|
||||
if (n < 1024) return `${n} B`
|
||||
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`
|
||||
if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`
|
||||
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断日期是否已超期(小于当前日期)
|
||||
* @param {string|Date} value 日期值
|
||||
* @returns {boolean}
|
||||
*/
|
||||
// 是否已逾期(日期早于今天且非空)
|
||||
export function isOverdue(value) {
|
||||
if (!value) return false
|
||||
const d = new Date(value)
|
||||
if (isNaN(d.getTime())) return false
|
||||
return d < new Date()
|
||||
if (Number.isNaN(d.getTime())) return false
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
d.setHours(0, 0, 0, 0)
|
||||
return d.getTime() < today.getTime()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user