项目筛选由两个增加至八个,增加质量管理,安全管理,现场管理

This commit is contained in:
马诗敏 2025-08-12 17:02:50 +08:00
parent 60b164f0c8
commit 25f57a4adb
2 changed files with 4062 additions and 1183 deletions

View File

@ -41,20 +41,6 @@
<!-- 简洁搜索区域 -->
<div class="search-section">
<a-card :bordered="false" class="search-card">
<!-- 搜索状态提示 -->
<div v-if="hasActiveFilters" class="search-status">
<icon-info-circle style="color: #667eea; margin-right: 8px;" />
<span>当前应用了搜索筛选条件</span>
<a-button
type="text"
size="small"
@click="handleReset"
style="margin-left: 8px; color: #667eea;"
>
清除所有筛选
</a-button>
</div>
<a-form layout="inline" :model="searchForm">
<a-form-item label="姓名">
<a-input
@ -63,7 +49,6 @@
style="width: 180px"
allow-clear
@press-enter="handleSearch"
@clear="handleSearch"
/>
</a-form-item>
<a-form-item label="项目岗位">
@ -72,7 +57,6 @@
placeholder="请选择项目岗位"
style="width: 150px"
allow-clear
@change="handleSearch"
>
<a-option
v-for="option in ROLE_TYPE_OPTIONS"
@ -89,7 +73,6 @@
placeholder="请选择状态"
style="width: 120px"
allow-clear
@change="handleSearch"
>
<a-option
v-for="option in STATUS_OPTIONS"
@ -102,12 +85,7 @@
</a-form-item>
<a-form-item>
<a-space>
<a-button
type="primary"
@click="handleSearch"
:loading="loading"
:disabled="!hasActiveFilters"
>
<a-button type="primary" @click="handleSearch">
<template #icon><icon-search /></template>
搜索
</a-button>
@ -121,7 +99,6 @@
</a-card>
</div>
<!-- 数据表格 -->
<GiTable
row-key="id"
@ -135,23 +112,6 @@
@page-size-change="onPageSizeChange"
@refresh="loadData"
>
<!-- 空状态显示 -->
<template #empty>
<div class="empty-state">
<icon-user-group style="font-size: 48px; color: #c9cdd4; margin-bottom: 16px;" />
<div class="empty-text">
<h3>{{ hasActiveFilters ? '没有找到匹配的团队成员' : '暂无团队成员数据' }}</h3>
<p v-if="hasActiveFilters">
请尝试调整搜索条件或
<a-link @click="handleReset">清除所有筛选</a-link>
</p>
<p v-else>
点击右上角的"新增成员"按钮来添加第一个团队成员
</p>
</div>
</div>
</template>
<!-- 项目岗位列 -->
<template #roleType="{ record }">
<span class="role-type-text">
@ -161,9 +121,9 @@
<!-- 状态列 -->
<template #status="{ record }">
<span class="status-tag" :class="`status-${record.status || 'INACTIVE'}`">
<a-tag :color="getStatusColor(record.status || 'INACTIVE')">
{{ getStatusText(record.status || 'INACTIVE') }}
</span>
</a-tag>
</template>
@ -380,7 +340,7 @@ const ROLE_TYPE_OPTIONS = [
const STATUS_OPTIONS = [
{ label: '可用', value: 'ACTIVE' },
{ label: '忙碌', value: 'SUSPENDED' },
{ label: '忙碌', value: 'SUSPENDEN' },
{ label: '离线', value: 'INACTIVE' }
]
@ -441,7 +401,7 @@ const statusForm = reactive<{
id: string | number
name: string
currentStatus: string
newStatus: 'ACTIVE' | 'SUSPENDED' | 'INACTIVE'
newStatus: 'ACTIVE' | 'SUSPENDEN' | 'INACTIVE'
}>({
id: '',
name: '',
@ -463,80 +423,56 @@ const loadData = async () => {
try {
console.log('正在加载项目团队成员数据项目ID:', projectId)
//
//
const queryParams: TeamMemberQuery = {
projectId: projectId,
page: pagination.current,
pageSize: pagination.pageSize,
name: searchForm.name || undefined,
position: searchForm.roleType || undefined, // 使position
position: searchForm.roleType || undefined,
status: searchForm.status || undefined
}
console.log('查询参数:', queryParams)
const response = await getProjectTeamMembers(queryParams)
console.log('API响应数据:', response)
console.log('API响应数据:', response.data)
//
let mappedData: TeamMemberResp[] = []
let total = 0
// response.data
const rawData = Array.isArray(response.data) ? response.data : [response.data]
if (response.data) {
//
if (response.data.list && Array.isArray(response.data.list)) {
mappedData = response.data.list.map((item: BackendTeamMemberResp) => {
return {
console.log('处理后的原始数据:', rawData)
//
const mappedData = rawData.map((item: BackendTeamMemberResp) => {
const mappedItem: TeamMemberResp = {
id: item.memberId,
name: item.name || '',
phone: item.phone || '',
email: item.email || '',
roleType: item.roleType || item.position || '', // 使roleTypefallbackposition
status: (item.status === 'ACTIVE' ? 'ACTIVE' : item.status === 'SUSPENDED' ? 'SUSPENDED' : 'INACTIVE') as 'ACTIVE' | 'SUSPENDED' | 'INACTIVE',
roleType: item.roleType || '', //
status: (item.status === 'ACTIVE' ? 'ACTIVE' : item.status === 'SUSPENDEN' ? 'SUSPENDEN' : 'INACTIVE') as 'ACTIVE' | 'SUSPENDEN' | 'INACTIVE',
joinDate: item.joinDate || '',
remark: item.remark || '',
avatar: item.userAvatar || ''
}
})
total = response.data.total || mappedData.length
}
//
else if (Array.isArray(response.data)) {
mappedData = response.data.map((item: BackendTeamMemberResp) => {
return {
id: item.memberId,
name: item.name || '',
phone: item.phone || '',
email: item.email || '',
roleType: item.roleType || item.position || '',
status: (item.status === 'ACTIVE' ? 'ACTIVE' : item.status === 'SUSPENDED' ? 'SUSPENDED' : 'INACTIVE') as 'ACTIVE' | 'SUSPENDED' | 'INACTIVE',
joinDate: item.joinDate || '',
remark: item.remark || '',
avatar: item.userAvatar || ''
}
})
total = mappedData.length
}
}
console.log('映射后的数据项:', mappedItem)
return mappedItem
})
dataList.value = mappedData
pagination.total = total
pagination.total = mappedData.length
console.log('团队成员数据加载完成,显示数据:', dataList.value.length, '条,总计:', pagination.total, '条')
} catch (error) {
console.error('团队成员数据加载失败:', error)
Message.error('团队成员数据加载失败')
dataList.value = []
pagination.total = 0
} finally {
loading.value = false
}
}
const handleSearch = async () => {
console.log('执行搜索,搜索条件:', searchForm)
pagination.current = 1
await loadData()
}
@ -549,18 +485,15 @@ const handleReset = () => {
status: ''
})
pagination.current = 1
//
loadData()
}
const onPageChange = (page: number) => {
console.log('页码变化:', page)
pagination.current = page
loadData()
}
const onPageSizeChange = (pageSize: number) => {
console.log('每页大小变化:', pageSize)
pagination.pageSize = pageSize
pagination.current = 1
loadData()
@ -664,7 +597,7 @@ const openStatusModal = (record: TeamMemberResp) => {
const saveStatus = async () => {
try {
await updateTeamMember(statusForm.id, {
status: statusForm.newStatus as 'ACTIVE' | 'SUSPENDED' | 'INACTIVE'
status: statusForm.newStatus as 'ACTIVE' | 'SUSPENDEN' | 'INACTIVE'
})
Message.success('状态更新成功')
statusModalVisible.value = false
@ -783,7 +716,7 @@ const getRoleTypeText = (roleType: string) => {
const getStatusColor = (status: string) => {
const colorMap: Record<string, string> = {
ACTIVE: 'success',
SUSPENDED: 'warning',
SUSPENDEN: 'warning',
INACTIVE: 'danger'
}
return colorMap[status] || 'danger'
@ -792,17 +725,12 @@ const getStatusColor = (status: string) => {
const getStatusText = (status: string) => {
const textMap: Record<string, string> = {
ACTIVE: '可用',
SUSPENDED: '忙碌',
SUSPENDEN: '忙碌',
INACTIVE: '离线'
}
return textMap[status] || '未知'
}
//
const hasActiveFilters = computed(() => {
return searchForm.name || searchForm.roleType || searchForm.status
})
//
onMounted(() => {
console.log('团队成员管理页面加载项目ID:', projectId)
@ -1011,29 +939,6 @@ onMounted(() => {
padding: 24px;
}
//
.search-status {
display: flex;
align-items: center;
margin-bottom: 16px;
padding: 12px 16px;
background: rgba(102, 126, 234, 0.1);
border-radius: 8px;
border-left: 4px solid #667eea;
font-size: 14px;
color: #4e5969;
.arco-btn {
padding: 2px 8px;
height: auto;
line-height: 1.4;
&:hover {
background: rgba(102, 126, 234, 0.2);
}
}
}
:deep(.arco-form-item) {
margin-bottom: 0;
margin-right: 20px;
@ -1064,7 +969,7 @@ onMounted(() => {
}
:deep(.arco-btn) {
border-radius: 8px;
border-radius: 8px;
font-weight: 600;
transition: all 0.3s ease;
@ -1072,78 +977,87 @@ onMounted(() => {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
&:hover {
transform: none;
box-shadow: none;
}
}
}
}
}
//
.search-results-info {
margin-bottom: 16px;
//
:deep(.gi-table) {
background: white;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
margin-bottom: 24px;
overflow: hidden;
.results-card {
background: linear-gradient(135deg, #f8f9ff 0%, #f0f2ff 100%);
border-radius: 12px;
box-shadow: 0 2px 12px rgba(102, 126, 234, 0.1);
border: 1px solid rgba(102, 126, 234, 0.1);
.arco-table-container {
overflow-x: auto;
overflow-y: auto;
}
.arco-table {
overflow: visible;
}
.arco-table-body {
overflow-y: auto;
}
//
.arco-table-thead {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
:deep(.arco-card-body) {
padding: 16px 20px;
}
.results-summary {
display: flex;
align-items: center;
font-size: 14px;
color: #4e5969;
.arco-table-th {
background: transparent !important;
border-bottom: 2px solid rgba(255, 255, 255, 0.2);
strong {
color: #667eea;
.arco-table-th-item-title {
color: white !important;
font-weight: 600;
font-size: 14px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
}
}
//
.arco-table-tbody {
.arco-table-tr {
transition: all 0.3s ease;
&:hover {
background: linear-gradient(135deg, #f8f9ff 0%, #f0f2ff 100%);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.1);
}
.arco-table-td {
border-bottom: 1px solid #f0f0f0;
padding: 16px 12px;
vertical-align: middle;
}
}
//
.arco-table-tr:nth-child(even) {
background: #fafbfc;
&:hover {
background: linear-gradient(135deg, #f8f9ff 0%, #f0f2ff 100%);
}
}
}
//
.arco-table-fixed-left,
.arco-table-fixed-right {
.arco-table-td {
background: white;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
}
}
//
.empty-state {
text-align: center;
padding: 60px 20px;
color: #c9cdd4;
.empty-text {
h3 {
margin: 0 0 12px 0;
font-size: 18px;
font-weight: 600;
color: #4e5969;
}
p {
margin: 8px 0;
font-size: 14px;
line-height: 1.6;
.arco-link {
color: #667eea;
font-weight: 500;
&:hover {
color: #4c5fd9;
}
}
}
}
}
.remark-content {
max-width: 180px;
@ -1196,58 +1110,11 @@ onMounted(() => {
transition: all 0.3s ease;
&:hover {
transform: scale(1.05);
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4);
}
}
//
.status-tag {
display: inline-block;
padding: 6px 12px;
border-radius: 20px;
font-weight: 600;
font-size: 12px;
text-align: center;
min-width: 60px;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
&:hover {
transform: scale(1.05);
}
&.status-ACTIVE {
background: linear-gradient(135deg, #52c41a 0%, #73d13d 100%);
color: white;
box-shadow: 0 2px 8px rgba(82, 196, 26, 0.3);
&:hover {
box-shadow: 0 4px 16px rgba(82, 196, 26, 0.4);
}
}
&.status-SUSPENDED {
background: linear-gradient(135deg, #faad14 0%, #ffc53d 100%);
color: white;
box-shadow: 0 2px 8px rgba(250, 173, 20, 0.3);
&:hover {
box-shadow: 0 4px 16px rgba(250, 173, 20, 0.4);
}
}
&.status-INACTIVE {
background: linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%);
color: white;
box-shadow: 0 2px 8px rgba(255, 77, 79, 0.3);
&:hover {
box-shadow: 0 4px 16px rgba(255, 77, 79, 0.4);
}
}
}
.member-form {
.form-row {
display: grid;
@ -1440,80 +1307,4 @@ onMounted(() => {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
}
//
:deep(.gi-table) {
background: white;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
margin-bottom: 24px;
overflow: hidden;
.arco-table-container {
overflow-x: auto;
overflow-y: auto;
}
.arco-table {
overflow: visible;
}
.arco-table-body {
overflow-y: auto;
}
//
.arco-table-thead {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
.arco-table-th {
background: transparent !important;
border-bottom: 2px solid rgba(255, 255, 255, 0.2);
.arco-table-th-item-title {
color: white !important;
font-weight: 600;
font-size: 14px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
}
}
//
.arco-table-tbody {
.arco-table-tr {
transition: all 0.3s ease;
&:hover {
background: linear-gradient(135deg, #f8f9ff 0%, #f0f2ff 100%);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.1);
}
.arco-table-td {
border-bottom: 1px solid #f0f0f0;
padding: 16px 12px;
vertical-align: middle;
}
}
//
.arco-table-tr:nth-child(even) {
background: #fafbfc;
&:hover {
background: linear-gradient(135deg, #f8f9ff 0%, #f0f2ff 100%);
}
}
}
//
.arco-table-fixed-left,
.arco-table-fixed-right {
.arco-table-td {
background: white;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
}
}
</style>

File diff suppressed because it is too large Load Diff