优化体验:统一业务状态与操作按钮文案

This commit is contained in:
wangzhibiao committed 2026-09-22 10:47:36 +08:00
1 parent 5871731edd
commit 2b1fcdb260
5 files changed
+78 -57

No files matched your search

@@ -27,10 +27,10 @@
</el-form-item>
<el-form-item label="住宿状态" prop="accommodationStatus">
<el-select v-model="queryParams.accommodationStatus" placeholder="全部状态" clearable>
<el-option label="预分配 (PRE_ASSIGNED)" :value="0" />
<el-option label="在住/已入住 (ACTIVE)" :value="1" />
<el-option label="已退宿 (CHECKED_OUT)" :value="2" />
<el-option label="已调房 (TRANSFERRED)" :value="3" />
<el-option label="预分配" :value="0" />
<el-option label="在住" :value="1" />
<el-option label="已退宿" :value="2" />
<el-option label="已调房" :value="3" />
</el-select>
</el-form-item>
<el-form-item>
@@ -67,7 +67,7 @@
<el-table-column label="床位号" align="center" prop="bedNo" width="80" />
<el-table-column label="住宿状态" align="center" width="120">
<template slot-scope="scope">
<el-tag v-if="scope.row.accommodationStatus === 1" type="success" size="small">在住 (ACTIVE)</el-tag>
<el-tag v-if="scope.row.accommodationStatus === 1" type="success" size="small">在住</el-tag>
<el-tag v-else-if="scope.row.accommodationStatus === 0" type="info" size="small">预分配</el-tag>
<el-tag v-else-if="scope.row.accommodationStatus === 2" type="danger" size="small">已退宿</el-tag>
<el-tag v-else-if="scope.row.accommodationStatus === 3" type="warning" size="small">已调房</el-tag>
@@ -165,9 +165,9 @@
</el-dialog>
<!-- 历史住宿履历对话框 -->
<el-dialog title="学员历史住宿履历 (Accommodation History)" :visible.sync="historyOpen" width="750px" append-to-body>
<el-dialog title="学员历史住宿记录" :visible.sync="historyOpen" width="750px" append-to-body>
<el-alert
title="住宿履历审计说明:系统保证同一学员在同一报名生命周期内仅存在至多一个生效中 (ACTIVE) 的住宿安排。"
title="住宿说明:系统按班级参训周期管理住宿,同一学员同一时间仅保留一条在住记录。"
type="info"
:closable="false"
show-icon
@@ -182,7 +182,7 @@
</el-table-column>
<el-table-column label="住宿状态" align="center" width="110">
<template slot-scope="scope">
<el-tag v-if="scope.row.accommodationStatus === 1" type="success" size="mini">当前在住 (ACTIVE)</el-tag>
<el-tag v-if="scope.row.accommodationStatus === 1" type="success" size="mini">在住</el-tag>
<el-tag v-else-if="scope.row.accommodationStatus === 2" type="danger" size="mini">已退宿</el-tag>
<el-tag v-else-if="scope.row.accommodationStatus === 3" type="warning" size="mini">已调房</el-tag>
<el-tag v-else size="mini">{{ scope.row.accommodationStatus }}</el-tag>
+46 -34
View File
@@ -2,7 +2,7 @@
<div class="app-container">
<el-alert
v-if="!dmsCapabilities.dmsEnabled"
title="系统提示:门禁系统当前处于未启用(DMS Disabled)状态,门禁凭据在线下发已暂停。根据安全策略,系统不会发起外部门禁操作。"
title="提示:门禁系统当前处于未启用状态,门禁权限在线下发已暂停,系统暂不向外部硬件设备同步数据。"
type="warning"
:closable="false"
show-icon
@@ -10,7 +10,7 @@
/>
<el-alert
v-else
title="门禁授权管理规范:门禁授权受学员报到确认、住宿安排及排课计划自动驱动。根据当前安全策略,在线密码凭证待业务侧安全交付方案确认(密文脱敏),系统不持久化亦不展示任何密码明文、Token或密钥。"
title="说明:门禁授权由学员报到与住宿安排自动联动;根据安全规范,系统仅对门禁授权状态进行管理,不展示密码明文与设备密钥。"
type="info"
:closable="false"
show-icon
@@ -44,14 +44,14 @@
</el-form-item>
<el-form-item label="授权状态" prop="authStatus">
<el-select v-model="queryParams.authStatus" placeholder="全部状态" clearable>
<el-option label="待授权 (PENDING_GRANT)" value="PENDING_GRANT" />
<el-option label="授权中 (GRANTING)" value="GRANTING" />
<el-option label="生效中 (ACTIVE)" value="ACTIVE" />
<el-option label="待注销 (PENDING_REVOKE)" value="PENDING_REVOKE" />
<el-option label="注销中 (REVOKING)" value="REVOKING" />
<el-option label="已注销 (REVOKED)" value="REVOKED" />
<el-option label="外部结果不确定 (AMBIGUOUS)" value="AMBIGUOUS" />
<el-option label="异常 (ERROR)" value="ERROR" />
<el-option label="待授权" value="PENDING_GRANT" />
<el-option label="授权中" value="GRANTING" />
<el-option label="生效中" value="ACTIVE" />
<el-option label="待注销" value="PENDING_REVOKE" />
<el-option label="注销中" value="REVOKING" />
<el-option label="已注销" value="REVOKED" />
<el-option label="外部结果待核实" value="AMBIGUOUS" />
<el-option label="异常" value="ERROR" />
</el-select>
</el-form-item>
<el-form-item>
@@ -85,42 +85,42 @@
</el-table-column>
<el-table-column label="宿舍安排" align="center" min-width="130">
<template slot-scope="scope">
<span>{{ scope.row.dormBuilding || '' }} {{ scope.row.dormRoom || '' }} ({{ scope.row.bedNo || '-' }}床)</span>
<span>{{ scope.row.dormBuilding || '' }} {{ scope.row.dormRoom || '' }} ({{ formatBedDisplay(scope.row.bedNo) }})</span>
</template>
</el-table-column>
<el-table-column label="业务授权状态" align="center" width="150">
<el-table-column label="业务授权状态" align="center" width="130">
<template slot-scope="scope">
<el-tag v-if="scope.row.authStatus === 'ACTIVE'" type="success" effect="dark" size="small">生效中 (ACTIVE)</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'PENDING_GRANT'" type="info" size="small">待授权 (PENDING_GRANT)</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'GRANTING'" type="warning" size="small">授权中 (GRANTING)</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'PENDING_REVOKE'" type="warning" size="small">等待DMS/待注销</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'REVOKING'" type="warning" size="small">注销中 (REVOKING)</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'REVOKED'" type="info" size="small">已注销 (REVOKED)</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'AMBIGUOUS'" type="danger" effect="dark" size="small">外部不确定 (AMBIGUOUS)</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'ERROR'" type="danger" size="small">异常 (ERROR)</el-tag>
<el-tag v-else size="small">{{ scope.row.authStatus || 'UNKNOWN' }}</el-tag>
<el-tag v-if="scope.row.authStatus === 'ACTIVE'" type="success" effect="dark" size="small">生效中</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'PENDING_GRANT'" type="info" size="small">待授权</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'GRANTING'" type="warning" size="small">授权中</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'PENDING_REVOKE'" type="warning" size="small">待注销</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'REVOKING'" type="warning" size="small">注销中</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'REVOKED'" type="info" size="small">已注销</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'AMBIGUOUS'" type="danger" effect="dark" size="small">外部结果待核实</el-tag>
<el-tag v-else-if="scope.row.authStatus === 'ERROR'" type="danger" size="small">异常</el-tag>
<el-tag v-else size="small">{{ scope.row.authStatus || '-' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="凭据类型" align="center" width="130">
<el-table-column label="凭据类型" align="center" width="120">
<template slot-scope="scope">
<el-tag size="mini" type="info">{{ scope.row.credentialType || 'ONLINE_PASSWORD' }}</el-tag>
<el-tag size="mini" type="info">{{ formatCredentialType(scope.row.credentialType) }}</el-tag>
</template>
</el-table-column>
<el-table-column label="安全凭据状态" align="center" min-width="160">
<el-table-column label="安全凭据状态" align="center" min-width="150">
<template slot-scope="{ row }">
<el-tag size="mini" type="warning">{{ row.authStatus ? '凭证待业务侧安全交付方案确认' : '待确认' }}</el-tag>
<el-tag size="mini" type="warning">{{ row.authStatus ? '待下发交付' : '待确认' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="权限生效时间" align="center" min-width="150">
<template slot-scope="scope">
<span v-if="scope.row.authStart">{{ parseTime(scope.row.authStart, '{y}-{m}-{d} {h}:{i}') }}</span>
<el-tag v-else size="mini" type="info">WAITING_FOR_PREREQUISITE</el-tag>
<span v-if="scope.row.authStart && scope.row.authStart !== 'WAITING_FOR_PREREQUISITE'">{{ parseTime(scope.row.authStart, '{y}-{m}-{d} {h}:{i}') }}</span>
<el-tag v-else size="mini" type="info">待下发</el-tag>
</template>
</el-table-column>
<el-table-column label="权限失效时间" align="center" min-width="150">
<template slot-scope="scope">
<span v-if="scope.row.authEnd">{{ parseTime(scope.row.authEnd, '{y}-{m}-{d} {h}:{i}') }}</span>
<el-tag v-else size="mini" type="info">WAITING_FOR_PREREQUISITE</el-tag>
<span v-if="scope.row.authEnd && scope.row.authEnd !== 'WAITING_FOR_PREREQUISITE'">{{ parseTime(scope.row.authEnd, '{y}-{m}-{d} {h}:{i}') }}</span>
<el-tag v-else size="mini" type="info">待下发</el-tag>
</template>
</el-table-column>
<el-table-column label="重试次数" align="center" prop="retryCount" width="80" />
@@ -159,7 +159,7 @@
<!-- 待授权/异常重发状态 -->
<span v-else-if="scope.row.authStatus === 'PENDING_GRANT' || scope.row.authStatus === 'ERROR'">
<el-tooltip v-if="!dmsCapabilities.dmsEnabled" content="DMS未启用,当前无法下发门禁凭据" placement="top">
<el-tooltip v-if="!dmsCapabilities.dmsEnabled" content="门禁服务未启用,暂无法下发门禁" placement="top">
<span style="display: inline-block; margin-left: 8px;">
<el-button
v-hasPermi="['train:access:credential']"
@@ -264,9 +264,9 @@
</div>
</el-dialog>
<!-- 一次性临时凭据展示对话框 (ADMIN_ONE_TIME_DISPLAY) -->
<!-- 一次性临时凭据展示对话框 -->
<el-dialog
title="一次性门禁凭据展示 (ADMIN_ONE_TIME_DISPLAY)"
title="一次性门禁密码展示"
:visible.sync="oneTimeDialogOpen"
width="550px"
append-to-body
@@ -275,14 +275,14 @@
:before-close="handleCloseOneTimeDialog"
>
<el-alert
title="凭据已提交下发,设备确认后生效。安全合规提示:该临时凭据仅在本次操作下发成功后由内存短暂展示一次!关闭弹窗或刷新页面后将永久清除,系统不持久化亦无法再次查询旧明文。"
title="凭据已提交下发,设备确认后生效。安全提示:该临时凭据仅由系统在本次操作成功后展示一次,关闭弹窗或刷新页面后将清除,请及时记录。"
type="warning"
:closable="false"
show-icon
style="margin-bottom: 20px;"
/>
<div style="text-align: center; padding: 20px 0;">
<div style="font-size: 14px; color: #606266; margin-bottom: 10px;">门锁一次性访问密码 (One-Time Credential)</div>
<div style="font-size: 14px; color: #606266; margin-bottom: 10px;">门锁临时访问密码</div>
<div style="font-size: 28px; font-weight: bold; letter-spacing: 4px; color: #409EFF; background: #F2F6FC; padding: 15px; border-radius: 4px; font-family: monospace;" id="oneTimeCredentialDisplay">
{{ maskedMode ? '••••••••' : oneTimeCredential }}
</div>
@@ -337,6 +337,18 @@ export default {
this.getList()
},
methods: {
formatBedDisplay(bedNo) {
if (!bedNo) return '-';
const str = String(bedNo).trim();
return str.endsWith('床') ? str : str + '床';
},
formatCredentialType(type) {
if (!type || type === 'ONLINE_PASSWORD') return '在线密码';
if (type === 'CARD') return '实体卡';
if (type === 'QR_CODE') return '二维码';
if (type === 'FACE') return '人脸凭证';
return type;
},
fetchCapabilities() {
getCapabilities().then(res => {
if (res.data) {
@@ -138,6 +138,15 @@ export function resolveSignInFeedback(err, defaultStudentName = '') {
msg = '签到操作失败';
}
// 清理内部研发前缀与技术词汇,提升业务可读性
if (typeof msg === 'string') {
msg = msg.replace(/^业务不变量校验失败[::]\s*/, '');
msg = msg.replace(/学员参训生命周期状态不合法/, '学员参训状态不符合签到要求');
if (msg.includes('DMS_DISABLED')) {
msg = '门禁系统未启用,无法同步外部硬件凭据';
}
}
// 绝对禁止包含“成功”字样如果其实是错误返回
return {
isSuccess: false,
+10 -10
View File
@@ -1,8 +1,8 @@
<template>
<div class="app-container">
<el-tabs v-model="activeTab" type="border-card">
<!-- Tab 1: 课次考勤与点名签到 (UC-17 培训管理员首次签到闭环) -->
<el-tab-pane label="课次考勤点名 / 签到" name="roster">
<!-- Tab 1: 课次考勤与点名签到 -->
<el-tab-pane label="课次考勤" name="roster">
<el-form :model="rosterQuery" size="small" :inline="true">
<el-form-item label="培训计划">
<el-select
@@ -50,7 +50,7 @@
</el-form>
<el-alert
title="课次应到学员考勤名册:展示该课次全部应到参训人员;未签到且已报到/在训学员可点击【签到】录入考勤事实;待报到或已结训学员禁止直接签到;已签到学员支持签退与留痕调整。"
title="课次应到学员考勤:展示该课次应到参训学员。已报到学员可点击【签到】录入出勤;待报到或已结训学员暂不可签到;已签到学员支持签退与考勤调整。"
type="info"
:closable="false"
show-icon
@@ -86,7 +86,7 @@
<el-table-column label="签到方式" align="center" width="100">
<template slot-scope="scope">{{ labelOf(checkinWays, scope.row.checkinWay) }}</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="180">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="190">
<template slot-scope="scope">
<el-button
v-if="computeActionEligibility(scope.row).canSignIn"
@@ -111,14 +111,14 @@
type="text"
icon="el-icon-edit"
@click="handleAdjust(scope.row)"
>调整</el-button>
>调整考勤</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<!-- Tab 2: 考勤流水记录 (原有流水与查询视图) -->
<el-tab-pane label="考勤流水记录" name="history">
<el-tab-pane label="考勤记录" name="history">
<el-form v-show="showSearch" ref="queryForm" :model="queryParams" size="small" :inline="true">
<el-form-item label="培训计划" prop="planName">
<el-input v-model="queryParams.planName" placeholder="请输入计划名称" clearable @keyup.enter.native="handleQuery" />
@@ -195,7 +195,7 @@
type="text"
icon="el-icon-edit"
@click="handleAdjust(scope.row)"
>调整</el-button>
>调整考勤</el-button>
</template>
</el-table-column>
</el-table>
@@ -210,8 +210,8 @@
</el-tab-pane>
</el-tabs>
<!-- 人工调整考勤对话框 (UC-19 / P0) -->
<el-dialog title="人工调整考勤 (Attendance Adjustment)" :visible.sync="adjustOpen" width="520px" append-to-body>
<!-- 人工调整考勤对话框 -->
<el-dialog title="调整考勤记录" :visible.sync="adjustOpen" width="520px" append-to-body>
<el-form ref="adjustForm" :model="adjustForm" :rules="adjustRules" label-width="100px">
<el-form-item label="学员姓名">
<span>{{ currentRecord.studentName || '-' }}</span>
@@ -235,7 +235,7 @@
v-model="adjustForm.remark"
type="textarea"
:rows="3"
placeholder="请输入人工调整原因或核验说明(如:班牌漏刷补录、事假证明核销,将全留痕记入审计流水)"
placeholder="请输入调整原因(如:班牌漏刷补录、事假核销等,将记入调整日志)"
maxlength="200"
show-word-limit
/>
@@ -97,7 +97,7 @@
type="text"
icon="el-icon-document"
@click="handleViewDetail(scope.row)"
>档案</el-button>
>学员档案</el-button>
<el-button
v-if="scope.row.enrollmentStatus === 0"
v-hasPermi="['train:report:confirm']"
@@ -106,7 +106,7 @@
icon="el-icon-check"
:disabled="isPlanLocked"
@click="handleConfirmReport(scope.row)"
>报到</el-button>
>确认报到</el-button>
<el-dropdown
v-if="scope.row.enrollmentStatus !== 4"
v-hasPermi="['train:enrollment:edit']"
@@ -119,7 +119,7 @@
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="2" :disabled="scope.row.enrollmentStatus === 2">标记请假</el-dropdown-item>
<el-dropdown-item command="3" :disabled="scope.row.enrollmentStatus === 3">标记退训</el-dropdown-item>
<el-dropdown-item command="3" :disabled="scope.row.enrollmentStatus === 3">标记放弃</el-dropdown-item>
<el-dropdown-item v-if="scope.row.enrollmentStatus === 2 || scope.row.enrollmentStatus === 3" command="resume">恢复参训</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
@@ -250,7 +250,7 @@
<div slot="tip" class="el-upload__tip">请上传 .xlsx 或 .xls 文件,单次最大支持 500 行数据。</div>
</el-upload>
</el-form-item>
<el-form-item label="学员档案策略">
<el-form-item label="新建学员档案">
<el-switch v-model="batchDialog.autoCreateStudent" active-text="学员不存在时自动建档" />
</el-form-item>
</el-form>
@@ -357,7 +357,7 @@ export default {
{ value: 0, label: '待报到' },
{ value: 1, label: '已报到' },
{ value: 2, label: '请假' },
{ value: 3, label: '退训' },
{ value: 3, label: '放弃' },
{ value: 4, label: '已完成' }
],
queryParams: {