优化条件筛选

This commit is contained in:
2026-08-11 16:42:10 +08:00 Unverified
parent eb20211f0e
commit 130bffbd01
6 changed files with 152 additions and 1 deletions
+57
View File
@@ -77,6 +77,16 @@ const references = reactive<Record<string, any[]>>({
campuses: [], colleges: [], majors: [], buildings: [], counselors: [],
})
const form = reactive<Record<string, any>>({})
const listFilters = reactive({
collegeId: undefined as string | undefined,
majorId: undefined as string | undefined,
grade: undefined as number | undefined,
campusId: undefined as string | undefined,
buildingId: undefined as string | undefined,
minimumCapacity: undefined as number | undefined,
teachingVenueNature: undefined as number | undefined,
isEnabled: undefined as boolean | undefined,
})
const title = computed(() => tabs.value.find((x) => x.key === active.value)?.label ?? '')
const canManage = computed(() =>
@@ -90,6 +100,10 @@ const filteredRows = computed(() => {
.filter(Boolean).some((value) => String(value).toLowerCase().includes(q)),
)
})
const filteredMajors = computed(() => references.majors.filter((item: any) =>
!listFilters.collegeId || item.collegeId === listFilters.collegeId))
const filteredBuildings = computed(() => references.buildings.filter((item: any) =>
!listFilters.campusId || item.campusId === listFilters.campusId))
const currentPage = ref(1)
const pageSize = ref(20)
const total = ref(0)
@@ -154,6 +168,18 @@ async function load(resetPage = true) {
page: currentPage.value,
pageSize: pageSize.value,
keyword: keyword.value.trim() || undefined,
...(active.value === 'classes' ? {
collegeId: listFilters.collegeId,
majorId: listFilters.majorId,
grade: listFilters.grade,
isEnabled: listFilters.isEnabled,
} : {
campusId: listFilters.campusId,
buildingId: listFilters.buildingId,
minimumCapacity: listFilters.minimumCapacity,
teachingVenueNature: listFilters.teachingVenueNature,
isEnabled: listFilters.isEnabled,
}),
}
: undefined,
})
@@ -187,6 +213,11 @@ async function loadReferences() {
async function changeTab() {
keyword.value = ''
Object.assign(listFilters, {
collegeId: undefined, majorId: undefined, grade: undefined,
campusId: undefined, buildingId: undefined, minimumCapacity: undefined,
teachingVenueNature: undefined, isEnabled: undefined,
})
await load()
}
@@ -388,6 +419,32 @@ watch(
<div class="table-toolbar">
<el-input v-model="keyword" :prefix-icon="Search" clearable placeholder="搜索编码、名称或所属单位" />
<template v-if="active === 'classes'">
<el-select v-model="listFilters.collegeId" clearable placeholder="全部学院" @change="() => { listFilters.majorId = undefined; load() }">
<el-option v-for="item in references.colleges" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<el-select v-model="listFilters.majorId" clearable filterable placeholder="全部专业" @change="load()">
<el-option v-for="item in filteredMajors" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<el-input-number v-model="listFilters.grade" :min="1900" :max="2200" controls-position="right" placeholder="入学年级" @change="load()" />
</template>
<template v-else-if="active === 'classrooms'">
<el-select v-model="listFilters.campusId" clearable placeholder="全部校区" @change="() => { listFilters.buildingId = undefined; load() }">
<el-option v-for="item in references.campuses" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<el-select v-model="listFilters.buildingId" clearable filterable placeholder="全部教学楼" @change="load()">
<el-option v-for="item in filteredBuildings" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
<el-select v-model="listFilters.teachingVenueNature" clearable placeholder="场地性质" @change="load()">
<el-option v-for="item in venueNatureOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-input-number v-model="listFilters.minimumCapacity" :min="1" controls-position="right" placeholder="最小容量" @change="load()" />
</template>
<el-select v-if="serverPaged" v-model="listFilters.isEnabled" clearable placeholder="全部状态" @change="load()">
<el-option label="启用" :value="true" />
<el-option label="停用" :value="false" />
</el-select>
<el-button :icon="Search" @click="load()">查询</el-button>
<el-button :icon="Refresh" @click="() => load(false)">刷新</el-button>
<template v-if="canManage">
<el-button :icon="Document" @click="downloadTemplate">下载模板</el-button>
+18 -1
View File
@@ -39,6 +39,7 @@ interface TeachingClassItem {
}
const terms = ref<any[]>([])
const colleges = ref<any[]>([])
const auth = useAuthStore()
const canManageSchedule = computed(() => auth.user?.roles.some(role => ['SuperAdmin', 'AcademicAdmin'].includes(role)) ?? false)
const classes = ref<TeachingClassItem[]>([])
@@ -46,6 +47,9 @@ const selected = ref<TeachingClassItem>()
const report = ref<any>()
const termId = ref<string>()
const keyword = ref('')
const collegeId = ref<string>()
const teacherKeyword = ref('')
const riskOnly = ref(false)
const page = ref(1)
const total = ref(0)
const pageSize = 12
@@ -109,6 +113,9 @@ async function loadClasses(reset = false) {
params: {
academicTermId: termId.value,
keyword: keyword.value.trim() || undefined,
collegeId: collegeId.value,
teacherKeyword: teacherKeyword.value.trim() || undefined,
riskOnly: riskOnly.value || undefined,
page: page.value,
pageSize,
},
@@ -343,7 +350,12 @@ watch(historyMetric, async () => {
onMounted(async () => {
try {
terms.value = (await http.get('/base-data/terms')).data
const [termResponse, collegeResponse] = await Promise.all([
http.get('/base-data/terms'),
http.get('/base-data/colleges'),
])
terms.value = termResponse.data
colleges.value = collegeResponse.data
termId.value = defaultAcademicTermId(terms.value)
} catch (error) {
ElMessage.error(apiErrorMessage(error))
@@ -409,7 +421,12 @@ onBeforeUnmount(() => {
<el-select v-model="termId" clearable placeholder="全部学期" style="width: 240px" @change="loadClasses(true)">
<el-option v-for="term in terms" :key="term.id" :label="academicTermLabel(term)" :value="term.id" />
</el-select>
<el-select v-model="collegeId" clearable placeholder="全部开课学院" style="width: 190px" @change="loadClasses(true)">
<el-option v-for="college in colleges" :key="college.id" :label="college.name" :value="college.id" />
</el-select>
<el-input v-model="keyword" clearable placeholder="课程、教学班名称或编号" :prefix-icon="Search" @keyup.enter="loadClasses(true)" />
<el-input v-model="teacherKeyword" clearable placeholder="任课教师姓名或工号" :prefix-icon="Search" @keyup.enter="loadClasses(true)" @clear="loadClasses(true)" />
<el-checkbox v-model="riskOnly" @change="loadClasses(true)">仅看预警班</el-checkbox>
<el-button type="primary" @click="loadClasses(true)">查询</el-button>
</section>
+22
View File
@@ -28,6 +28,10 @@ const editingRoles = ref<string[]>([])
const editingStaffNumber = ref('')
const editingCollegeId = ref<string>()
const keyword = ref('')
const roleFilter = ref<string>()
const collegeFilter = ref<string>()
const enabledFilter = ref<boolean>()
const loginFilter = ref<boolean>()
const page = ref(1)
const total = ref(0)
const pageSize = 20
@@ -69,6 +73,10 @@ async function load(resetPage = false) {
page: page.value,
pageSize,
keyword: keyword.value.trim() || undefined,
roleName: roleFilter.value,
collegeId: collegeFilter.value,
isEnabled: enabledFilter.value,
hasLoggedIn: loginFilter.value,
},
}),
http.get('/users/roles'),
@@ -231,6 +239,20 @@ onMounted(load)
@clear="load(true)"
@keyup.enter="load(true)"
/>
<el-select v-model="roleFilter" clearable placeholder="全部角色" @change="load(true)">
<el-option v-for="role in roles" :key="role.name" :label="role.name" :value="role.name" />
</el-select>
<el-select v-model="collegeFilter" clearable placeholder="全部学院" @change="load(true)">
<el-option v-for="college in colleges" :key="college.id" :label="college.name" :value="college.id" />
</el-select>
<el-select v-model="enabledFilter" clearable placeholder="全部账号状态" @change="load(true)">
<el-option label="启用" :value="true" />
<el-option label="停用" :value="false" />
</el-select>
<el-select v-model="loginFilter" clearable placeholder="全部登录情况" @change="load(true)">
<el-option label="已登录过" :value="true" />
<el-option label="从未登录" :value="false" />
</el-select>
<el-button :icon="Search" @click="load(true)">查询</el-button>
<el-button :icon="Document" @click="downloadTemplate">下载模板</el-button>
<el-button :icon="Upload" :loading="importing" @click="chooseImportFile">Excel 导入</el-button>