机房电脑打中文要切输入法,选姓名前先切一次法太别扭。现在 zhangsan、zs、 xiaoxian 都能搜到张三/曾小贤,中文照旧能打。 用 pinyin-pro 的 match 而不是自己拼一份拼音串比对:多音字它两个读音都认, 单田芳搜 stf 和 dtf 都出得来,曾小贤搜 zxx 和 cengxiaoxian 也都出得来 —— 自己拼只会留下默认读音那一个,姓氏恰恰是多音字重灾区。 词典有 85 KB(gzip),静态引入会压进首屏,所以改成打开登录框才 import。 已登录的人一次都不会下载(构建产物里它是独立 chunk,只被 default 布局 动态引用;实测页面加载 0 个请求,打开登录框才有 1 个)。拉不下来时退回 纯中文匹配,不至于让人登不上。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YQCLjAmz6pPXMNGoZmvAmC
This commit is contained in:
@@ -48,6 +48,7 @@
|
|||||||
"nanoid": "^6.0.1",
|
"nanoid": "^6.0.1",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^4.0.3",
|
"pinia": "^4.0.3",
|
||||||
|
"pinyin-pro": "^3.29.3",
|
||||||
"skulpt": "^1.2.0",
|
"skulpt": "^1.2.0",
|
||||||
"vue": "^3.5.41",
|
"vue": "^3.5.41",
|
||||||
"vue-chartjs": "^5.3.4",
|
"vue-chartjs": "^5.3.4",
|
||||||
|
|||||||
@@ -26,6 +26,28 @@ const adminRef = useTemplateRef("adminRef")
|
|||||||
const studentPasswordRef = useTemplateRef("studentPasswordRef")
|
const studentPasswordRef = useTemplateRef("studentPasswordRef")
|
||||||
const classUserOptions = ref<SelectOption[]>([])
|
const classUserOptions = ref<SelectOption[]>([])
|
||||||
const classUserLoading = ref(false)
|
const classUserLoading = ref(false)
|
||||||
|
// 姓名支持拼音和拼音缩写搜索(张三 ← zhangsan / zs)。pinyin-pro 带着一份几百 K 的
|
||||||
|
// 词典,静态引入会压进首屏 —— 改成打开登录框才拉,已登录的人一次都不会下载。
|
||||||
|
// 用 match 而不是自己拼拼音串:多音字它两个读音都认(单田芳 ← stf 和 dtf 都能搜到)。
|
||||||
|
type MatchFn = typeof import("pinyin-pro").match
|
||||||
|
const pinyinMatch = shallowRef<MatchFn | null>(null)
|
||||||
|
async function ensurePinyin() {
|
||||||
|
if (pinyinMatch.value) return
|
||||||
|
try {
|
||||||
|
pinyinMatch.value = (await import("pinyin-pro")).match
|
||||||
|
} catch {
|
||||||
|
// 拉不下来就只剩中文匹配,不至于让人登不上
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function filterClassUser(pattern: string, option: SelectOption) {
|
||||||
|
const keyword = pattern.trim()
|
||||||
|
if (!keyword) return true
|
||||||
|
const label = String(option.label ?? "")
|
||||||
|
if (label.includes(keyword)) return true
|
||||||
|
return pinyinMatch.value
|
||||||
|
? pinyinMatch.value(label, keyword, { continuous: true }) !== null
|
||||||
|
: false
|
||||||
|
}
|
||||||
// 空串是「没有我所在的班级」,null 才是没选 —— 往届的班级毕业后会从后台配置里删掉,
|
// 空串是「没有我所在的班级」,null 才是没选 —— 往届的班级毕业后会从后台配置里删掉,
|
||||||
// 这一项是他们唯一的入口,写完整用户名登录
|
// 这一项是他们唯一的入口,写完整用户名登录
|
||||||
const OTHER_CLASS = ""
|
const OTHER_CLASS = ""
|
||||||
@@ -179,6 +201,7 @@ watch(classList, restoreLastClass)
|
|||||||
// 每次打开都从干净的表单开始,别把上一个人的姓名和密码留在框里
|
// 每次打开都从干净的表单开始,别把上一个人的姓名和密码留在框里
|
||||||
watch(loginModalOpen, (open) => {
|
watch(loginModalOpen, (open) => {
|
||||||
if (!open) return
|
if (!open) return
|
||||||
|
ensurePinyin()
|
||||||
resetForm()
|
resetForm()
|
||||||
studentRef.value?.restoreValidation()
|
studentRef.value?.restoreValidation()
|
||||||
adminRef.value?.restoreValidation()
|
adminRef.value?.restoreValidation()
|
||||||
@@ -188,6 +211,7 @@ watch(loginModalOpen, (open) => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
authStore.clearLoginError()
|
authStore.clearLoginError()
|
||||||
restoreLastClass()
|
restoreLastClass()
|
||||||
|
if (loginModalOpen.value) ensurePinyin()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -228,9 +252,10 @@ onMounted(() => {
|
|||||||
:options="classUserOptions"
|
:options="classUserOptions"
|
||||||
:loading="classUserLoading"
|
:loading="classUserLoading"
|
||||||
filterable
|
filterable
|
||||||
|
:filter="filterClassUser"
|
||||||
name="class-username"
|
name="class-username"
|
||||||
id="login-class-username"
|
id="login-class-username"
|
||||||
placeholder="选择姓名"
|
placeholder="选择姓名,也可以打拼音"
|
||||||
@update:value="onUsernamePicked"
|
@update:value="onUsernamePicked"
|
||||||
/>
|
/>
|
||||||
<n-input
|
<n-input
|
||||||
|
|||||||
3
bun.lock
3
bun.lock
@@ -75,6 +75,7 @@
|
|||||||
"nanoid": "^6.0.1",
|
"nanoid": "^6.0.1",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^4.0.3",
|
"pinia": "^4.0.3",
|
||||||
|
"pinyin-pro": "^3.29.3",
|
||||||
"skulpt": "^1.2.0",
|
"skulpt": "^1.2.0",
|
||||||
"vue": "^3.5.41",
|
"vue": "^3.5.41",
|
||||||
"vue-chartjs": "^5.3.4",
|
"vue-chartjs": "^5.3.4",
|
||||||
@@ -1241,6 +1242,8 @@
|
|||||||
|
|
||||||
"pinia": ["pinia@4.0.3", "https://registry.npmjs.com/pinia/-/pinia-4.0.3.tgz", { "dependencies": { "nostics": "^1.1.4" }, "peerDependencies": { "@vue/devtools-api": "^8.1.5", "typescript": ">=5.6.0", "vue": "^3.5.11" }, "optionalPeers": ["typescript"] }, "sha512-XMQqpvjgG7LMqVhhFUzKLT4KEbsYbfZZ0CZU9PgdFm1O2VKBmIkykL8+SfNhOaT7sR0wT6BEgKT0YNDYWgmVRA=="],
|
"pinia": ["pinia@4.0.3", "https://registry.npmjs.com/pinia/-/pinia-4.0.3.tgz", { "dependencies": { "nostics": "^1.1.4" }, "peerDependencies": { "@vue/devtools-api": "^8.1.5", "typescript": ">=5.6.0", "vue": "^3.5.11" }, "optionalPeers": ["typescript"] }, "sha512-XMQqpvjgG7LMqVhhFUzKLT4KEbsYbfZZ0CZU9PgdFm1O2VKBmIkykL8+SfNhOaT7sR0wT6BEgKT0YNDYWgmVRA=="],
|
||||||
|
|
||||||
|
"pinyin-pro": ["pinyin-pro@3.29.3", "", {}, "sha512-+UU9bx6vfDw8amOJGHm0TE0rdQl8VPylsDWviQ5OOQ3e+on1xRP4OqDbiDuMT5OISgvfl/Y6ez1BBRaIP80GLQ=="],
|
||||||
|
|
||||||
"pkg-types": ["pkg-types@2.3.1", "https://registry.npmjs.com/pkg-types/-/pkg-types-2.3.1.tgz", { "dependencies": { "confbox": "^0.2.4", "exsolve": "^1.0.8", "pathe": "^2.0.3" } }, "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg=="],
|
"pkg-types": ["pkg-types@2.3.1", "https://registry.npmjs.com/pkg-types/-/pkg-types-2.3.1.tgz", { "dependencies": { "confbox": "^0.2.4", "exsolve": "^1.0.8", "pathe": "^2.0.3" } }, "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg=="],
|
||||||
|
|
||||||
"points-on-curve": ["points-on-curve@0.2.0", "https://registry.npmjs.com/points-on-curve/-/points-on-curve-0.2.0.tgz", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
|
"points-on-curve": ["points-on-curve@0.2.0", "https://registry.npmjs.com/points-on-curve/-/points-on-curve-0.2.0.tgz", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
|
||||||
|
|||||||
Reference in New Issue
Block a user