kindergarten/reading-platform-frontend/src/views/school/settings/SettingsView.vue

195 lines
6.8 KiB
Vue
Raw Normal View History

<template>
2026-03-03 13:59:02 +08:00
<div class="p-0 min-h-screen bg-gradient-to-b from-[#FFF8F0] to-white">
<div class="mb-6">
<h1 class="text-2xl font-semibold text-[#2D3436] m-0 mb-2 flex items-center gap-3"><SettingOutlined /> 系统设置</h1>
<p class="text-sm text-[#636E72] m-0">配置学校基本信息和通知偏好</p>
</div>
<a-spin :spinning="loading">
2026-03-03 13:59:02 +08:00
<div class="flex flex-col gap-6">
<!-- 基本信息 -->
2026-03-03 13:59:02 +08:00
<div class="bg-white rounded-2xl overflow-hidden shadow-[0_4px_15px_rgba(0,0,0,0.05)]">
<div class="flex items-center gap-3 py-5 px-6 border-b border-[#F5F5F5] bg-[#FAFAFA]">
<span class="text-xl text-[#FF8C42] flex items-center"><HomeOutlined /></span>
<h3 class="m-0 text-base font-semibold text-[#2D3436]">基本信息</h3>
</div>
2026-03-03 13:59:02 +08:00
<div class="p-6 max-md:p-4">
<a-form
:model="formData"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 16 }"
>
<a-form-item label="学校名称">
<a-input v-model:value="formData.schoolName" placeholder="请输入学校名称" />
</a-form-item>
<a-form-item label="学校Logo">
2026-03-03 13:59:02 +08:00
<div class="flex items-center">
<div class="flex items-center gap-4" v-if="formData.schoolLogo">
<img :src="formData.schoolLogo" alt="Logo" class="w-20 h-20 object-contain rounded-lg border border-[#E0E0E0]" />
<div class="logo-actions">
<a-button type="link" size="small" @click="formData.schoolLogo = ''">
<DeleteOutlined /> 删除
</a-button>
</div>
</div>
<a-upload
v-else
:show-upload-list="false"
:before-upload="handleLogoUpload"
accept="image/*"
>
2026-03-03 13:59:02 +08:00
<div class="w-20 h-20 border-2 border-dashed border-[#D9D9D9] rounded-lg flex flex-col items-center justify-center cursor-pointer transition-all text-[#636E72] hover:border-[#FF8C42] hover:text-[#FF8C42]">
<PlusOutlined />
2026-03-03 13:59:02 +08:00
<span class="text-xs mt-1">上传Logo</span>
</div>
</a-upload>
</div>
</a-form-item>
<a-form-item label="学校地址">
<a-textarea
v-model:value="formData.address"
placeholder="请输入学校地址"
:rows="2"
/>
</a-form-item>
</a-form>
</div>
</div>
<!-- 通知设置 -->
2026-03-03 13:59:02 +08:00
<div class="bg-white rounded-2xl overflow-hidden shadow-[0_4px_15px_rgba(0,0,0,0.05)]">
<div class="flex items-center gap-3 py-5 px-6 border-b border-[#F5F5F5] bg-[#FAFAFA]">
<span class="text-xl text-[#FF8C42] flex items-center"><BellOutlined /></span>
<h3 class="m-0 text-base font-semibold text-[#2D3436]">通知设置</h3>
</div>
2026-03-03 13:59:02 +08:00
<div class="p-6 max-md:p-4">
<a-form
:label-col="{ span: 8 }"
:wrapper-col="{ span: 12 }"
>
<a-form-item label="课程完成通知">
<a-switch
v-model:checked="formData.notifyOnLesson"
checked-children="开"
un-checked-children="关"
/>
2026-03-03 13:59:02 +08:00
<span class="ml-3 max-md:ml-0 max-md:mt-1 max-md:block text-[#636E72] text-xs">当教师完成一次授课后发送通知</span>
</a-form-item>
<a-form-item label="任务提醒通知">
<a-switch
v-model:checked="formData.notifyOnTask"
checked-children="开"
un-checked-children="关"
/>
2026-03-03 13:59:02 +08:00
<span class="ml-3 max-md:ml-0 max-md:mt-1 max-md:block text-[#636E72] text-xs">当有新的阅读任务时发送通知</span>
</a-form-item>
<a-form-item label="成长档案通知">
<a-switch
v-model:checked="formData.notifyOnGrowth"
checked-children="开"
un-checked-children="关"
/>
2026-03-03 13:59:02 +08:00
<span class="ml-3 max-md:ml-0 max-md:mt-1 max-md:block text-[#636E72] text-xs">当更新学生成长档案时发送通知</span>
</a-form-item>
</a-form>
</div>
</div>
<!-- 保存按钮 -->
2026-03-03 13:59:02 +08:00
<div class="flex justify-center p-6 bg-white rounded-2xl shadow-[0_4px_15px_rgba(0,0,0,0.05)]">
<a-button type="primary" size="large" :loading="saving" @click="handleSave">
<SaveOutlined /> 保存设置
</a-button>
</div>
</div>
</a-spin>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { message } from 'ant-design-vue';
import {
SettingOutlined,
HomeOutlined,
BellOutlined,
SaveOutlined,
PlusOutlined,
DeleteOutlined,
} from '@ant-design/icons-vue';
import { getSettings, updateSettings, type SystemSettings, type UpdateSettingsDto } from '@/api/school';
import { fileApi } from '@/api/file';
const loading = ref(false);
const saving = ref(false);
const formData = ref<UpdateSettingsDto>({
schoolName: '',
schoolLogo: '',
address: '',
notifyOnLesson: true,
notifyOnTask: true,
notifyOnGrowth: false,
});
const loadSettings = async () => {
loading.value = true;
try {
const data = await getSettings();
formData.value = {
schoolName: data.schoolName || '',
schoolLogo: data.schoolLogo || '',
address: data.address || '',
notifyOnLesson: data.notifyOnLesson,
notifyOnTask: data.notifyOnTask,
notifyOnGrowth: data.notifyOnGrowth,
};
} catch (error) {
console.error('Failed to load settings:', error);
message.error('加载设置失败');
} finally {
loading.value = false;
}
};
const handleLogoUpload = async (file: File) => {
try {
const result = await fileApi.uploadFile(file, 'cover');
formData.value.schoolLogo = result.filePath;
message.success('Logo上传成功');
} catch (error) {
console.error('Failed to upload logo:', error);
message.error('Logo上传失败');
}
return false;
};
const handleSave = async () => {
saving.value = true;
try {
await updateSettings(formData.value);
message.success('设置保存成功');
} catch (error) {
console.error('Failed to save settings:', error);
message.error('保存设置失败');
} finally {
saving.value = false;
}
};
onMounted(() => {
loadSettings();
});
</script>
<style scoped>
@media (max-width: 768px) {
:deep(.ant-form-item-label) {
padding-bottom: 8px !important;
}
:deep(.ant-form-item) {
margin-bottom: 16px;
}
}
</style>