fix(project): 优化项目与成员页面卡片布局、表单基线对齐与表格统一列宽
This commit is contained in:
parent
b2b52c9bd8
commit
c474a13332
@ -1,3 +1,11 @@
|
||||
## 2026年10月17日 “项目与成员”页面布局与表格对齐优化
|
||||
|
||||
- [✓] 复审通过:优化左侧“我的项目”卡片布局,项目名称与权限标签采用单行水平两端对齐,避免纵向压缩拉伸,保持文字左对齐。
|
||||
- [✓] 复审通过:优化右侧“授予角色”表单基线对齐,为“项目角色”统一高度基线(22px),解决输入框与下拉选择框上下不对齐的问题。
|
||||
- [✓] 复审通过:重构成员表格为固定列宽与靠左对齐规范(col-member 38%、col-status 22%、col-roles 40%),采用独立状态徽章与账户 ID 结构,避免列宽扭曲与文字换行混乱。
|
||||
- [✓] 复审通过:修复底部分页控件“每页 [select] 位成员”横向排布,强制单行水平排列(white-space: nowrap),彻底杜绝“位成员”文字竖向折行。
|
||||
- [✓] 复审通过:执行前端 356 项单元测试全部 PASS,编译构建产物成功。
|
||||
|
||||
## 2026年10月17日 系统设置单项独立保存与光标等待修复验收
|
||||
|
||||
- [✓] 复审通过:系统设置重构为单项独立配置与保存,每个选项卡(服务监听、ACME 设置、DNS API 验证、邮件通知)内置独立保存按钮及局部校验逻辑。
|
||||
|
||||
@ -1,3 +1,11 @@
|
||||
## 2026年10月17日 “项目与成员”页面视觉与布局对齐整改
|
||||
|
||||
- [✓] 优化左侧项目卡片 flex 布局,项目名称左对齐并单行省略,右侧权限标签紧凑展示不折行。
|
||||
- [✓] 统一右侧添加成员表单项基线与按钮垂直对齐,解决成员账户与项目角色列高度不一问题。
|
||||
- [✓] 表格采用 table-layout: fixed 与靠左对齐,统一各列宽度定义,美化成员 ID 与状态标签。
|
||||
- [✓] 修复分页每页条数区域换行问题,确保“每页 [select] 位成员”横向对齐不折行。
|
||||
- [✓] 前端测试 356 项全通过并成功部署至第一台服务器(8.137.23.95)。
|
||||
|
||||
## 2026年10月17日 系统设置单项独立保存与光标等待修复验收
|
||||
|
||||
- [✓] 复审通过:系统设置重构为单项独立配置与保存,每个选项卡(服务监听、ACME 设置、DNS API 验证、邮件通知)内置独立保存按钮及局部校验逻辑。
|
||||
|
||||
@ -103,9 +103,9 @@
|
||||
.project-list button {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid #e2e8f0;
|
||||
@ -143,12 +143,16 @@
|
||||
}
|
||||
|
||||
.project-list button strong {
|
||||
font-size: 15px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: inherit;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.project-list button small {
|
||||
flex-shrink: 0;
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
@ -156,6 +160,7 @@
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.project-list button[aria-current="true"] small {
|
||||
@ -188,10 +193,13 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.project-account-field > span {
|
||||
display: flex;
|
||||
.project-account-field > span,
|
||||
.project-role-field-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.project-management input,
|
||||
@ -286,6 +294,7 @@
|
||||
|
||||
.project-member-table table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
@ -301,17 +310,77 @@
|
||||
color: #475569;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
text-align: left;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.project-member-table th.col-member,
|
||||
.project-member-table td.col-member {
|
||||
width: 38%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.project-member-table th.col-status,
|
||||
.project-member-table td.col-status {
|
||||
width: 22%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.project-member-table th.col-roles,
|
||||
.project-member-table td.col-roles {
|
||||
width: 40%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.project-member-table td {
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
color: #334155;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
line-height: 1.5;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.project-member-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.project-member-name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.project-member-id {
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
font-family: ui-monospace, monospace;
|
||||
}
|
||||
|
||||
.project-status-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 3px 8px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.project-status-badge.active {
|
||||
color: #16a34a;
|
||||
background: #f0fdf4;
|
||||
border: 1px solid #bbf7d0;
|
||||
}
|
||||
|
||||
.project-status-badge:not(.active) {
|
||||
color: #92400e;
|
||||
background: #fffbeb;
|
||||
border: 1px solid #fde68a;
|
||||
}
|
||||
|
||||
.project-member-table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
@ -384,11 +453,18 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.project-member-pagination label {
|
||||
display: flex;
|
||||
.project-member-pagination label,
|
||||
.member-page-size-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-right: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.member-page-size-label select {
|
||||
width: auto;
|
||||
min-width: 68px;
|
||||
}
|
||||
|
||||
.project-empty {
|
||||
@ -491,4 +567,4 @@
|
||||
.project-editor {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +101,8 @@ const {
|
||||
<option v-for="account in accountChoices" :key="account.id" :value="account.id">{{ account.username }}</option>
|
||||
</datalist>
|
||||
</label>
|
||||
<label>项目角色
|
||||
<label>
|
||||
<span class="project-role-field-label">项目角色</span>
|
||||
<select v-model="memberForm.role" :disabled="savingMember || loadingMembers">
|
||||
<option v-for="role in projectRoles" :key="role.value" :value="role.value">{{ role.label }}</option>
|
||||
</select>
|
||||
@ -117,28 +118,46 @@ const {
|
||||
</div>
|
||||
<div class="project-member-table" :aria-busy="loadingMembers">
|
||||
<table>
|
||||
<thead><tr><th scope="col">成员</th><th scope="col">状态</th><th scope="col">项目角色</th></tr></thead>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="col-member">成员</th>
|
||||
<th scope="col" class="col-status">状态</th>
|
||||
<th scope="col" class="col-roles">项目角色</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="member in members" :key="member.user_id">
|
||||
<td><strong>{{ member.username }}</strong><small>{{ member.user_id }}</small></td>
|
||||
<td>{{ member.status === "active" ? "正常" : "已停用" }}</td>
|
||||
<td><div class="project-role-list">
|
||||
<span v-for="role in member.roles" :key="role" class="project-role">
|
||||
{{ roleLabel(role) }}
|
||||
<button type="button" :disabled="savingMember || loadingMembers" :aria-label="`撤销 ${member.username} 的${roleLabel(role)}角色`" @click="requestRevoke(member, role)">撤销</button>
|
||||
<td class="col-member">
|
||||
<div class="project-member-info">
|
||||
<strong class="project-member-name">{{ member.username }}</strong>
|
||||
<small class="project-member-id" :title="member.user_id">账户 ID:{{ member.user_id }}</small>
|
||||
</div>
|
||||
</td>
|
||||
<td class="col-status">
|
||||
<span class="project-status-badge" :class="member.status">
|
||||
{{ member.status === "active" ? "正常" : "已停用" }}
|
||||
</span>
|
||||
</div></td>
|
||||
</td>
|
||||
<td class="col-roles">
|
||||
<div class="project-role-list">
|
||||
<span v-for="role in member.roles" :key="role" class="project-role">
|
||||
{{ roleLabel(role) }}
|
||||
<button type="button" :disabled="savingMember || loadingMembers" :aria-label="`撤销 ${member.username} 的${roleLabel(role)}角色`" @click="requestRevoke(member, role)">撤销</button>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="!members.length"><td colspan="3" class="project-empty">{{ loadingMembers ? "正在读取成员……" : "本页暂无成员" }}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="project-pagination project-member-pagination">
|
||||
<label>每页
|
||||
<label class="member-page-size-label">
|
||||
<span>每页</span>
|
||||
<select :value="memberPageSize" :disabled="savingMember || loadingMembers" @change="changeMemberPageSize($event.target.value)">
|
||||
<option v-for="size in pageSizes" :key="size" :value="size">{{ size }}</option>
|
||||
</select>
|
||||
位成员
|
||||
<span>位成员</span>
|
||||
</label>
|
||||
<button type="button" :disabled="savingMember || loadingMembers || memberPage === 0" @click="previousMemberPage">上一页</button>
|
||||
<span>第 {{ memberPage + 1 }} 页</span>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user