Files
en-edu/enlish-vue/src/layouts/components/AddClassDialog.vue
lbw fb29acc145 feat(ui): 提升界面响应式支持和移动端适配体验
- 新增移动端全屏对话框支持及标签宽度和位置动态调整,优化新增班级、年级和学生弹窗布局
- 所有对话框增加屏幕宽度监听,实现自动切换移动端和桌面端样式
- 表格组件增加移动端列表视图,隐藏侧边栏并改进分页和按钮自适应,提升小屏幕浏览体验
- Dialog及详情弹窗添加最大高度限制并启用滚动,防止移动端显示区域拥挤
- 登录页增加安全区域内边距,保证iOS等设备显示完整性
- 新增移动端菜单抽屉组件,支持手机端侧边栏交互显示
- 学生详情页调整词汇热力图列数,实现移动端更合理布局
- 表格和按钮统一增设触控友好大尺寸区域,提升移动端操作便利性
- 修正后端空词汇ID查询问题,避免空列表导致查询异常
- 统一隐藏小屏幕时的固定侧边栏,避免界面混乱和重复显示
- 搜索页和上传页表格添加移动端适配样式和展开收起逻辑,提升列表浏览灵活性
2026-01-05 18:47:50 +08:00

105 lines
2.9 KiB
Vue

<template>
<el-dialog v-model="visible" title="新增班级" width="480px" :fullscreen="isMobile" :close-on-click-modal="false">
<div class="space-y-4" v-loading="loading">
<el-form :label-width="isMobile ? 0 : 80" :label-position="isMobile ? 'top' : 'right'">
<el-form-item label="班级名称">
<el-input v-model="name" placeholder="请输入班级名称,如:二班" clearable class="w-full" />
</el-form-item>
<el-form-item label="年级">
<el-select v-model="gradeId" placeholder="请选择年级" class="w-full sm:w-[260px]">
<el-option v-for="g in gradeOptions" :key="g.id" :label="g.title" :value="g.id" />
</el-select>
</el-form-item>
</el-form>
</div>
<template #footer>
<div class="footer-actions flex sm:justify-end gap-2 sm:flex-row flex-col">
<el-button class="w-full sm:w-auto touch-target" @click="visible = false">取消</el-button>
<el-button class="w-full sm:w-auto touch-target" type="primary" :disabled="!canSubmit" @click="handleSubmit">确定</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
import { getGradeList } from '@/api/grade'
import { addClass } from '@/api/class'
const props = defineProps({
modelValue: { type: Boolean, default: false },
defaultGradeId: { type: [Number, String], default: null }
})
const emit = defineEmits(['update:modelValue', 'success'])
const visible = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
const loading = ref(false)
const name = ref('')
const gradeId = ref(null)
const gradeOptions = ref([])
const isMobile = ref(false)
const canSubmit = computed(() => name.value.trim().length > 0 && !!gradeId.value)
async function fetchGrades() {
loading.value = true
try {
const res = await getGradeList(1, 100)
const d = res?.data
gradeOptions.value = Array.isArray(d?.data) ? d.data : []
if (props.defaultGradeId && !gradeId.value) {
gradeId.value = Number(props.defaultGradeId)
}
} finally {
loading.value = false
}
}
async function handleSubmit() {
if (!canSubmit.value) return
loading.value = true
try {
await addClass(name.value.trim(), Number(gradeId.value))
ElMessage.success('新增班级成功')
emit('success')
visible.value = false
} finally {
loading.value = false
}
}
function updateIsMobile() {
isMobile.value = window.matchMedia('(max-width: 768px)').matches
}
watch(
() => props.modelValue,
(v) => {
if (v) {
name.value = ''
gradeId.value = props.defaultGradeId ? Number(props.defaultGradeId) : null
fetchGrades()
updateIsMobile()
}
}
)
onMounted(() => {
updateIsMobile()
window.addEventListener('resize', updateIsMobile)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', updateIsMobile)
})
</script>
<style scoped>
.footer-actions :deep(.el-button + .el-button) {
margin-left: 0;
}
</style>