- 学生名字一律只显示名字(老号 ks232张三 显示成 张三),顶栏、首页问候、悬停提示、请假名单、比赛成绩表都一样 - 全服 / 年级排名、全部提交、几个班同时举手时,名字后面淡写班级;提交列表的名字列窄,只写班号(陈长 258) - AI 班级分析点名「要多关心的同学」时不再带 ks 前缀 - 建号查重补漏:同班同名也比真名(加过数字的张三2、编号制老号);名字自己带数字(王芳1)也认得出被占; 导入时后端再拦一次同班同名,建号页要等查重结果对上当前名单才能点 - 登录名单换成新接口 /classes/:c/members(名字按界面规则剥,换过班的老号不再露出全名), 旧接口原样留给上线时还开着旧登录页的机房电脑 - 后台手写老格式 ks232张三 新建用户、没选班时按前缀补班级;PUT /me/profile 只带真名时不再 500 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
221d264701
commit
2bda05a978
32 files changed
+229
-111
No files matched your search
@@ -86,25 +86,36 @@ const duplicates = computed(() => {
|
||||
// 这个班已经有的同名账号(老号按剥掉 ks 前缀的名字比),顺带拿回每个名字会建成的用户名:停手半秒再去查
|
||||
const existing = ref<{ name: string; username: string; createTime: string | null }[]>([])
|
||||
const checking = ref(false)
|
||||
/** 查重结果对应的是哪一份「班级 + 名单」:和眼前的对不上(刚改过、还在防抖)就不让建 */
|
||||
const inputKey = computed(() => `${klass.value}\n${names.value.join('\n')}`)
|
||||
const checkedKey = ref('')
|
||||
// 改得快时前一次请求可能后回来,只认最后发出去的那次
|
||||
let checkSeq = 0
|
||||
watchDebounced(
|
||||
() => `${klass.value}\n${names.value.join('\n')}`,
|
||||
async () => {
|
||||
inputKey,
|
||||
async (key) => {
|
||||
const seq = ++checkSeq
|
||||
const list = [...new Set(names.value)]
|
||||
if (!list.length || !klass.value || list.length > 500) {
|
||||
existing.value = []
|
||||
suggested.value = new Map()
|
||||
checkedKey.value = ''
|
||||
return
|
||||
}
|
||||
checking.value = true
|
||||
try {
|
||||
const res = await checkUsernames(klass.value, list)
|
||||
if (seq !== checkSeq) return
|
||||
existing.value = res.existing
|
||||
suggested.value = new Map(list.map((name, i) => [name, res.usernames[i] ?? name]))
|
||||
checkedKey.value = key
|
||||
} catch {
|
||||
if (seq !== checkSeq) return
|
||||
existing.value = []
|
||||
suggested.value = new Map()
|
||||
checkedKey.value = ''
|
||||
} finally {
|
||||
checking.value = false
|
||||
if (seq === checkSeq) checking.value = false
|
||||
}
|
||||
},
|
||||
{ debounce: 500, immediate: true },
|
||||
@@ -112,7 +123,7 @@ watchDebounced(
|
||||
|
||||
const tooMany = computed(() => rows.value.length > 500)
|
||||
const issueCount = computed(() => (classError.value ? 1 : 0) + duplicates.value.length + existing.value.length + (tooMany.value ? 1 : 0))
|
||||
const canSubmit = computed(() => rows.value.length > 0 && !issueCount.value && !checking.value && !!klass.value)
|
||||
const canSubmit = computed(() => rows.value.length > 0 && !issueCount.value && !checking.value && !!klass.value && checkedKey.value === inputKey.value)
|
||||
|
||||
// ---------------------------------------------------------------- 建号
|
||||
|
||||
@@ -220,7 +231,7 @@ body{margin:12mm;font-family:"Microsoft YaHei","PingFang SC",sans-serif}
|
||||
<template v-if="rows.length">
|
||||
<div class="head">
|
||||
<b>会建这 {{ rows.length }} 个账号</b>
|
||||
<n-tag v-if="!issueCount && !checking && klass" type="success" :bordered="false" round> 没有重名 </n-tag>
|
||||
<n-tag v-if="!issueCount && !checking && klass && checkedKey === inputKey" type="success" :bordered="false" round> 没有重名 </n-tag>
|
||||
<n-tag v-if="issueCount" type="warning" :bordered="false" round> 有 {{ issueCount }} 处要先改 </n-tag>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import UserNameCell from './components/UserNameCell.vue'
|
||||
import PasswordCell from './components/PasswordCell.vue'
|
||||
import { PROBLEM_PERMISSION, USER_TYPE } from 'utils/constants'
|
||||
import { useRouteQuery } from '@vueuse/router'
|
||||
import { NO_CLASS, STUDENT_ROLES, type ImportUsersRequest } from '@oj2/contract'
|
||||
import { legacyClassOf, NO_CLASS, STUDENT_ROLES, type ImportUsersRequest } from '@oj2/contract'
|
||||
import { downloadAccountsCsv } from './accountsCsv'
|
||||
import { classLabel, groupClassOptions } from 'utils/classes'
|
||||
import { useConfigStore } from 'shared/store/config'
|
||||
@@ -315,10 +315,21 @@ async function handleEditUser() {
|
||||
}
|
||||
// http 拦截器只对 login-required / permission-denied 自动弹提示,
|
||||
// 其余业务错误(比如班级号位数不对)不接住就什么都不显示
|
||||
if (create.value && !userEditing.value.className && legacyClassOf(userEditing.value.username) === undefined) {
|
||||
message.error('用户名里 ks 后面的班级号位数不对,班级号要是 3~4 位数字')
|
||||
return
|
||||
}
|
||||
try {
|
||||
if (create.value) {
|
||||
const newUser: ImportUsersRequest['users'] = [
|
||||
[userEditing.value.username, password.value, userEditing.value.email ?? '', userEditing.value.realName ?? '', userEditing.value.className],
|
||||
[
|
||||
userEditing.value.username,
|
||||
password.value,
|
||||
userEditing.value.email ?? '',
|
||||
userEditing.value.realName ?? '',
|
||||
// 没选班、但手写的是老格式 ks232张三:按前缀补上班级
|
||||
userEditing.value.className ?? legacyClassOf(userEditing.value.username) ?? null,
|
||||
],
|
||||
]
|
||||
await importUsers(newUser)
|
||||
listUsers()
|
||||
|
||||
Reference in new issue
Block a user