fix(im/registrationInvite): add input verification for bound user search

1. add computed state to check if bind user input is unverified
2. disable confirm button and show warning tip when input is unverified
3. track last searched keyword to validate user input
4. add submission guard to prevent unvalidated submissions
This commit is contained in:
Austin
2026-09-21 14:45:10 +08:00
parent 8fad32e396
commit c4ab970fb7
@@ -20,6 +20,7 @@
<span class="bound-user-name">{{ boundUser.nickname || boundUser.username || boundUser.phone || '--' }}({{ boundUser.userId }})</span>
<n-button text type="error" @click="clearBoundUser">清除</n-button>
</div>
<div v-if="bindInputUnverified" class="bind-user-tip">输入的用户ID未验证,请先点击搜索</div>
</n-form-item>
<n-form-item label="到期时间" path="expiresAt">
<n-date-picker v-model:value="formValue.expiresAt" type="datetime" clearable />
@@ -31,14 +32,14 @@
<template #action>
<n-space justify="end">
<n-button @click="closeModal">取消</n-button>
<n-button type="primary" :loading="loading" @click="submit">确认</n-button>
<n-button type="primary" :loading="loading" :disabled="bindInputUnverified" @click="submit">确认</n-button>
</n-space>
</template>
</n-modal>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { computed, reactive, ref } from 'vue';
import { useMessage } from 'naive-ui';
import { BatchCreate, Create } from '@/api/im/registrationInvite';
import { List as UserList } from '@/api/imUser';
@@ -55,6 +56,12 @@
const bindUserInput = ref('');
const searching = ref(false);
const boundUser = ref<any>(null);
// 最近一次已通过搜索验证的输入值;输入框有值但不等于它时视为未验证
const lastSearchedKeyword = ref('');
const bindInputUnverified = computed(() => {
const input = bindUserInput.value.trim();
return !!input && input !== lastSearchedKeyword.value;
});
const formValue = reactive({
quantity: 100,
expiresAt: Date.now() + 7 * 24 * 3600 * 1000,
@@ -78,6 +85,7 @@
formValue.boundUserId = '';
bindUserInput.value = '';
boundUser.value = null;
lastSearchedKeyword.value = '';
showModal.value = true;
}
@@ -100,6 +108,8 @@
page: 1,
perPage: 1,
});
// 搜索成功返回即视为已验证(无论是否找到用户)
lastSearchedKeyword.value = keyword;
const user = res?.list?.[0];
if (!user) {
message.warning('未找到该用户,将不绑定用户');
@@ -124,10 +134,16 @@
boundUser.value = null;
formValue.boundUserId = '';
bindUserInput.value = '';
lastSearchedKeyword.value = '';
}
async function submit() {
await formRef.value?.validate();
// 输入了用户ID但未点击搜索验证时,禁止提交,兜底拦截
if (bindInputUnverified.value) {
message.warning('请先点击搜索验证输入的用户ID');
return;
}
loading.value = true;
try {
const params: any = {
@@ -174,5 +190,12 @@
.bound-user-name {
flex: 1;
}
.bind-user-tip {
width: 100%;
margin-top: 4px;
color: #f0a020;
font-size: 12px;
}
</style>