feat(join): B1 名单加入申请 —— 学生提交 + 管理端审批(V7 存 AES 密文)
按契约「服务端转 HMAC、不落明文」设计会写不进名册:collect_roster.id_card_no 是 NOT NULL 的密文列,而申请表只有 hash 与 mask(三条替代路都被排除)。 V7 给 collect_join_request 补 id_card_cipher(与名册同一把密钥/算法),审批时原样搬进名册, 明文全程只在提交请求的内存里存在过。V7 之前的老申请明确提示重新提交,不静默建一条 永远过不了校验的名册行。 另修 F-20:自述班级不能借用姓名规范化(姓名要「张 三」→「张三」,班级名里的空格有意义)。 验证:scripts/e2e-m2-join.py 50/50。
This commit is contained in:
@@ -32,8 +32,19 @@
|
||||
|
||||
<view v-if="error" class="verify__error">{{ error }}</view>
|
||||
|
||||
<!--
|
||||
核验失败时给一条**受控通道**(FR-509 / 客户确认后新增)。
|
||||
注意两件事:
|
||||
1) 这条通道**不绕过门禁** —— 申请期间仍然不能填,去申请页会说清这一点;
|
||||
2) 它只在真失败过之后才出现(`error` 非空),不是一进来就摆个"申请"按钮。
|
||||
否则会有学生绕过核验直接去申请,把管理员的待办当成人工客服。
|
||||
-->
|
||||
<button v-if="error" class="verify__btn verify__btn--ghost" @click="gotoJoin">
|
||||
申请加入名单
|
||||
</button>
|
||||
|
||||
<view class="verify__foot">
|
||||
核对不上?先确认姓名和证件号没有打错。仍然不行请联系班主任。
|
||||
核对不上?先确认姓名和证件号没有打错。仍然不行可点上面的「申请加入名单」。
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -214,6 +225,20 @@ function next() {
|
||||
})
|
||||
}
|
||||
|
||||
/** 去申请加入名单(FR-509 的入口)—— 带上已填的姓名与证件号,省他再输一遍。 */
|
||||
function gotoJoin() {
|
||||
const s = sceneFromUrl()
|
||||
const params = new URLSearchParams({
|
||||
scene: s,
|
||||
taskId: String(ctx.value.taskId || 0),
|
||||
// 只把**已经打过的字**带过去。这不是"预填答案":门禁刚判定它不匹配,
|
||||
// 带过去是为了让他少打一遍,而不是暗示它是对的。
|
||||
name: realName.value.trim(),
|
||||
idCardNo: idCardNo.value.trim()
|
||||
})
|
||||
uni.navigateTo({ url: `/pages/join/join?${params.toString()}` })
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
loadContext(options?.scene || '')
|
||||
})
|
||||
@@ -318,6 +343,14 @@ page {
|
||||
color: #0000004d;
|
||||
background: #e8e8e8;
|
||||
}
|
||||
|
||||
/* 次要动作("申请加入名单"):主按钮才是"核对并继续",
|
||||
两个实心按钮并排会让人分不清哪个是推荐路径 */
|
||||
&--ghost {
|
||||
margin-top: 20rpx;
|
||||
color: $primary;
|
||||
background: #eaf1fd;
|
||||
}
|
||||
}
|
||||
|
||||
&__error {
|
||||
|
||||
Reference in New Issue
Block a user