refactor(security): 重构安全配置并优化测试环境

- 移除旧的测试套件和UAT测试文件
- 更新密码编码器配置使用BCrypt strength=12
- 添加用户角色关联表和相关服务
- 优化前端日期显示格式
- 清理无用资源和配置文件
- 增强测试数据管理和清理功能
This commit is contained in:
张翔
2026-03-27 13:00:22 +08:00
parent ce30893a96
commit af44c23f21
294 changed files with 16057 additions and 22601 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ export interface User {
phone: string
avatar: string
status: UserStatus
roles: string[]
roles: number[]
createdAt: string
updatedAt: string
}
@@ -0,0 +1,53 @@
export const formatDateTime = (dateTime: string | Date | null | undefined): string => {
if (!dateTime) return '-'
try {
const date = typeof dateTime === 'string' ? new Date(dateTime) : dateTime
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
} catch (error) {
console.error('时间格式化失败:', error)
return String(dateTime)
}
}
export const formatDate = (date: string | Date | null | undefined): string => {
if (!date) return '-'
try {
const d = typeof date === 'string' ? new Date(date) : date
const year = d.getFullYear()
const month = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
} catch (error) {
console.error('日期格式化失败:', error)
return String(date)
}
}
export const formatTime = (time: string | Date | null | undefined): string => {
if (!time) return '-'
try {
const t = typeof time === 'string' ? new Date(time) : time
const hours = String(t.getHours()).padStart(2, '0')
const minutes = String(t.getMinutes()).padStart(2, '0')
const seconds = String(t.getSeconds()).padStart(2, '0')
return `${hours}:${minutes}:${seconds}`
} catch (error) {
console.error('时间格式化失败:', error)
return String(time)
}
}
@@ -76,7 +76,11 @@
prop="loginTime"
label="登录时间"
sortable="custom"
/>
>
<template #default="{ row }">
{{ formatDateTime(row.loginTime) }}
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:current-page="pagination.current"
@@ -96,6 +100,7 @@
import { ref, reactive, onMounted } from 'vue'
import { Search } from '@element-plus/icons-vue'
import request from '@/utils/request'
import { formatDateTime } from '@/utils/dateFormat'
const loading = ref(false)
const dataSource = ref([])
@@ -106,7 +106,11 @@
prop="createdAt"
label="操作时间"
sortable="custom"
/>
>
<template #default="{ row }">
{{ formatDateTime(row.createdAt) }}
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:current-page="pagination.current"
@@ -126,6 +130,7 @@
import { ref, reactive, onMounted } from 'vue'
import { Search, User, Document, Setting, Lock, View, Edit, Delete, Plus, Download } from '@element-plus/icons-vue'
import { operationLogApi, OperationLog } from '@/api/operationLog'
import { formatDateTime } from '@/utils/dateFormat'
const loading = ref(false)
const dataSource = ref<OperationLog[]>([])
@@ -58,7 +58,11 @@
<el-table-column
prop="createdAt"
label="上传时间"
/>
>
<template #default="{ row }">
{{ formatDateTime(row.createdAt) }}
</template>
</el-table-column>
<el-table-column
prop="createBy"
label="上传人"
@@ -96,6 +100,7 @@ import { ref, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Upload, Search } from '@element-plus/icons-vue'
import request from '@/utils/request'
import { formatDateTime } from '@/utils/dateFormat'
const loading = ref(false)
const dataSource = ref([])
@@ -56,7 +56,11 @@
<el-table-column
prop="createdAt"
label="发布时间"
/>
>
<template #default="{ row }">
{{ formatDateTime(row.createdAt) }}
</template>
</el-table-column>
<el-table-column
label="操作"
width="150"
@@ -146,6 +150,7 @@
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/utils/request'
import { formatDateTime } from '@/utils/dateFormat'
const loading = ref(false)
const dataSource = ref([])
@@ -191,17 +191,17 @@ const systemInfo = reactive({
const fetchStats = async () => {
loading.value = true
try {
const userCountRes: any = await request.get('/users/count')
stats.userCount = userCountRes || 0
const [userCountRes, roleCountRes, todayLoginRes, operationLogRes] = await Promise.allSettled([
request.get('/users/count'),
request.get('/roles/count'),
request.get('/logs/login/today/count'),
request.get('/logs/operation/count')
])
const roleCountRes: any = await request.get('/roles/count')
stats.roleCount = roleCountRes || 0
const todayLoginRes: any = await request.get('/logs/login/today/count')
stats.todayLogin = todayLoginRes || 0
const operationLogRes: any = await request.get('/logs/operation/count')
stats.operationLog = operationLogRes || 0
stats.userCount = userCountRes.status === 'fulfilled' ? (userCountRes.value || 0) : 0
stats.roleCount = roleCountRes.status === 'fulfilled' ? (roleCountRes.value || 0) : 0
stats.todayLogin = todayLoginRes.status === 'fulfilled' ? (todayLoginRes.value || 0) : 0
stats.operationLog = operationLogRes.status === 'fulfilled' ? (operationLogRes.value || 0) : 0
} catch (error) {
console.error('Failed to fetch stats:', error)
} finally {
@@ -210,14 +210,12 @@ const fetchStats = async () => {
}
const fetchRecentLogins = async () => {
loading.value = true
try {
const res: any = await request.get('/logs/login/recent?limit=10')
recentLogins.value = res || []
} catch (error) {
console.error('Failed to fetch recent logins:', error)
} finally {
loading.value = false
recentLogins.value = []
}
}
@@ -76,7 +76,11 @@
prop="createdAt"
label="创建时间"
sortable="custom"
/>
>
<template #default="{ row }">
{{ formatDateTime(row.createdAt) }}
</template>
</el-table-column>
<el-table-column
label="操作"
width="250"
@@ -213,6 +217,7 @@ import { Search } from '@element-plus/icons-vue'
import { roleApi, type Role, type CreateRoleRequest, type UpdateRoleRequest, type Permission } from '@/api/role.api'
import { handleApiError } from '@/utils/errorHandler'
import { RoleStatus } from '@/constants/status'
import { formatDateTime } from '@/utils/dateFormat'
const loading = ref(false)
const dataSource = ref<Role[]>([])
@@ -81,7 +81,11 @@
prop="createdAt"
label="创建时间"
sortable="custom"
/>
>
<template #default="{ row }">
{{ formatDateTime(row.createdAt) }}
</template>
</el-table-column>
<el-table-column
label="操作"
width="250"
@@ -219,6 +223,7 @@ import { userApi, type User, type CreateUserRequest, type UpdateUserRequest } fr
import { roleApi, type Role } from '@/api/role.api'
import { handleApiError } from '@/utils/errorHandler'
import { UserStatus, StatusHelper } from '@/constants/status'
import { formatDateTime } from '@/utils/dateFormat'
const loading = ref(false)
const dataSource = ref<User[]>([])
@@ -376,12 +381,9 @@ const handleAssignRoles = async (row: User) => {
const roles = await roleApi.getAll()
allRoles.value = roles.map((role: Role) => ({
key: role.id,
label: role.name
label: role.roleName
}))
selectedRoles.value = row.roles.map((roleName: string) => {
const role = roles.find((r: Role) => r.name === roleName)
return role ? role.id : 0
}).filter((id: number) => id > 0)
selectedRoles.value = row.roles || []
roleDialogVisible.value = true
} catch (error) {
handleApiError(error)