diff --git a/reading-platform-frontend/src/constants/loginAccount.ts b/reading-platform-frontend/src/constants/loginAccount.ts
new file mode 100644
index 0000000..1e32859
--- /dev/null
+++ b/reading-platform-frontend/src/constants/loginAccount.ts
@@ -0,0 +1,9 @@
+/**
+ * 登录账号规则(与租户管理、学校端教师/家长创建约定一致)
+ * 字母开头,4-20 位字母、数字或下划线
+ */
+export const LOGIN_ACCOUNT_PATTERN = /^[a-zA-Z][a-zA-Z0-9_]{3,19}$/;
+
+export const LOGIN_ACCOUNT_PLACEHOLDER = '字母开头,4-20位';
+
+export const LOGIN_ACCOUNT_PATTERN_MESSAGE = '字母开头,4-20位字母数字或下划线';
diff --git a/reading-platform-frontend/src/views/admin/tenants/TenantListView.vue b/reading-platform-frontend/src/views/admin/tenants/TenantListView.vue
index 010fc8f..590c49e 100644
--- a/reading-platform-frontend/src/views/admin/tenants/TenantListView.vue
+++ b/reading-platform-frontend/src/views/admin/tenants/TenantListView.vue
@@ -126,7 +126,7 @@
-
+
@@ -351,6 +351,11 @@ import {
type CourseCollectionResponse,
} from '@/api/admin';
import { getDiscountTypeText } from '@/api/collections';
+import {
+ LOGIN_ACCOUNT_PATTERN,
+ LOGIN_ACCOUNT_PATTERN_MESSAGE,
+ LOGIN_ACCOUNT_PLACEHOLDER,
+} from '@/constants/loginAccount';
// 搜索表单
const searchForm = reactive({
@@ -414,7 +419,10 @@ const formRules = {
name: [{ required: true, message: '请输入学校名称' }],
loginAccount: [
{ required: true, message: '请输入登录账号' },
- { pattern: /^[a-zA-Z][a-zA-Z0-9_]{3,19}$/, message: '字母开头,4-20位字母数字或下划线' },
+ {
+ pattern: LOGIN_ACCOUNT_PATTERN,
+ message: LOGIN_ACCOUNT_PATTERN_MESSAGE,
+ },
],
contactPerson: [{ required: true, message: '请输入联系人' }],
contactPhone: [
diff --git a/reading-platform-frontend/src/views/school/parents/ParentListView.vue b/reading-platform-frontend/src/views/school/parents/ParentListView.vue
index b1c33f4..d723317 100644
--- a/reading-platform-frontend/src/views/school/parents/ParentListView.vue
+++ b/reading-platform-frontend/src/views/school/parents/ParentListView.vue
@@ -148,7 +148,7 @@
-
+
@@ -335,6 +335,11 @@ import {
getClasses,
} from '@/api/school';
import type { Parent, CreateParentDto, ParentChild, Student } from '@/api/school';
+import {
+ LOGIN_ACCOUNT_PATTERN,
+ LOGIN_ACCOUNT_PATTERN_MESSAGE,
+ LOGIN_ACCOUNT_PLACEHOLDER,
+} from '@/constants/loginAccount';
// 状态辅助函数
const getParentStatusText = (status: string): string => {
@@ -412,14 +417,19 @@ const formState = reactive({
password: '',
});
-const rules: Record = {
+const rules = computed(() => ({
name: [{ required: true, message: '请输入家长姓名', trigger: 'blur' }],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' },
],
- loginAccount: [{ required: true, message: '请输入登录账号', trigger: 'blur' }],
-};
+ loginAccount: [
+ { required: true, message: '请输入登录账号', trigger: 'blur' },
+ ...(!isEdit.value
+ ? [{ pattern: LOGIN_ACCOUNT_PATTERN, message: LOGIN_ACCOUNT_PATTERN_MESSAGE, trigger: 'blur' }]
+ : []),
+ ],
+}));
const loadParents = async () => {
loading.value = true;
diff --git a/reading-platform-frontend/src/views/school/teachers/TeacherListView.vue b/reading-platform-frontend/src/views/school/teachers/TeacherListView.vue
index 25715f1..5f2f67d 100644
--- a/reading-platform-frontend/src/views/school/teachers/TeacherListView.vue
+++ b/reading-platform-frontend/src/views/school/teachers/TeacherListView.vue
@@ -152,7 +152,7 @@
-
+
@@ -234,6 +234,11 @@ import {
getClasses,
} from '@/api/school';
import type { Teacher, CreateTeacherDto, ClassInfo } from '@/api/school';
+import {
+ LOGIN_ACCOUNT_PATTERN,
+ LOGIN_ACCOUNT_PATTERN_MESSAGE,
+ LOGIN_ACCOUNT_PLACEHOLDER,
+} from '@/constants/loginAccount';
// 状态辅助函数
const getTeacherStatusText = (status: string): string => {
@@ -301,14 +306,19 @@ const formState = reactive(
status: 'ACTIVE',
});
-const rules: Record = {
+const rules = computed(() => ({
name: [{ required: true, message: '请输入教师姓名', trigger: 'blur' }],
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' },
],
- loginAccount: [{ required: true, message: '请输入登录账号', trigger: 'blur' }],
-};
+ loginAccount: [
+ { required: true, message: '请输入登录账号', trigger: 'blur' },
+ ...(!isEdit.value
+ ? [{ pattern: LOGIN_ACCOUNT_PATTERN, message: LOGIN_ACCOUNT_PATTERN_MESSAGE, trigger: 'blur' }]
+ : []),
+ ],
+}));
const loadTeachers = async () => {
loading.value = true;