|
|
@@ -0,0 +1,674 @@
|
|
|
+<template>
|
|
|
+ <view class="page_select_object">
|
|
|
+ <CommonHeader title="选择通知对象" @back="goBack"></CommonHeader>
|
|
|
+
|
|
|
+ <view class="tabs_container" :style="{ top: tabsTop + 'rpx' }">
|
|
|
+ <view v-for="tab in tabs" :key="tab.key" class="tab_item" :class="{ active: activeTab === tab.key, disabled: editMode }"
|
|
|
+ @click="!editMode && handleTabChange(tab.key)">
|
|
|
+ <text class="tab_text">{{ tab.label }}</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <SearchBar v-model="searchKeyword" @search="searchTree" :border="true" :isFixed="true" :top="searchBarTop + 'rpx'" :zIndex="100"></SearchBar>
|
|
|
+
|
|
|
+ <scroll-view scroll-y class="content_list" :style="{ paddingTop: contentPaddingTop + 'rpx' }">
|
|
|
+ <TreeNodeNoDedup :tree-data="treeData" :expanded-ids="expandedIds" @toggle-expand="toggleExpand"
|
|
|
+ @toggle-select="toggleSelect" />
|
|
|
+ </scroll-view>
|
|
|
+
|
|
|
+ <view class="select_footer">
|
|
|
+ <view class="confirm_btn" @click="handleConfirm">
|
|
|
+ <text class="btn_text">确定(已选{{ selectedCount }}人)</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, computed, onMounted } from 'vue';
|
|
|
+import TreeNodeNoDedup from '@/components/treeNodeNoDedup.vue';
|
|
|
+import SearchBar from '@/components/searchBar.vue';
|
|
|
+import CommonHeader from '@/components/commonHeader.vue';
|
|
|
+import overview from '@/reqApi/overview.js';
|
|
|
+import { useSafeArea } from '@/common/safeArea';
|
|
|
+
|
|
|
+const { statusBarHeight, initSafeArea } = useSafeArea();
|
|
|
+
|
|
|
+const HEADER_CONTENT_HEIGHT = 130;
|
|
|
+const TABS_HEIGHT = 120;
|
|
|
+const SEARCHBAR_HEIGHT = 84;
|
|
|
+const SPACING = 16;
|
|
|
+
|
|
|
+const tabsTop = computed(() => statusBarHeight.value + HEADER_CONTENT_HEIGHT);
|
|
|
+const searchBarTop = computed(() => statusBarHeight.value + HEADER_CONTENT_HEIGHT + TABS_HEIGHT);
|
|
|
+const contentPaddingTop = computed(() => statusBarHeight.value + HEADER_CONTENT_HEIGHT + TABS_HEIGHT + SEARCHBAR_HEIGHT + SPACING);
|
|
|
+
|
|
|
+const activeTab = ref('department');
|
|
|
+const searchKeyword = ref('');
|
|
|
+const schoolYearId = ref('');
|
|
|
+const editMode = ref(false);
|
|
|
+const noticeType = ref(0);
|
|
|
+const selectedUserIds = ref([]);
|
|
|
+
|
|
|
+const tabs = [
|
|
|
+ { key: 'department', label: '按部门' },
|
|
|
+ { key: 'subject', label: '按学科' },
|
|
|
+ { key: 'grade', label: '按年级' },
|
|
|
+ { key: 'permission', label: '按权限' },
|
|
|
+ { key: 'student', label: '按学生' }
|
|
|
+];
|
|
|
+
|
|
|
+const treeData = ref([]);
|
|
|
+const fullTreeData = ref([]);
|
|
|
+const expandedIds = ref([]);
|
|
|
+
|
|
|
+// 转换按部门接口数据为树形结构(不去重)
|
|
|
+const transformDepartmentData = (data) => {
|
|
|
+ if (!data || !Array.isArray(data)) return [];
|
|
|
+
|
|
|
+ return data.map(dept => {
|
|
|
+ const groups = (dept.groupVOS || []).map(group => ({
|
|
|
+ id: `${dept.id}_${group.groupId}`,
|
|
|
+ name: group.groupName,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: (group.groupUserVOS || []).map(user => ({
|
|
|
+ id: user.userId,
|
|
|
+ name: user.teacherName,
|
|
|
+ userId: user.userId,
|
|
|
+ userAccount: user.userAccount,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false
|
|
|
+ }))
|
|
|
+ }));
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: dept.id,
|
|
|
+ name: dept.name,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: groups
|
|
|
+ };
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 转换按学科的数据为树形结构(不去重)
|
|
|
+const transformSubjectData = (data) => {
|
|
|
+ if (!data || !Array.isArray(data)) return [];
|
|
|
+
|
|
|
+ return data.map(subject => {
|
|
|
+ const grades = (subject.gradePersonVos || []).map(grade => ({
|
|
|
+ id: `${subject.subjectCode}_${grade.schoolYearGradeId || grade.gradeCode}`,
|
|
|
+ name: grade.gradeName,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: (grade.personVoList || []).map(user => ({
|
|
|
+ id: user.userId,
|
|
|
+ name: user.teacherName,
|
|
|
+ userId: user.userId,
|
|
|
+ userAccount: user.userAccount,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false
|
|
|
+ }))
|
|
|
+ }));
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: `subject_${subject.subjectCode}`,
|
|
|
+ name: subject.subjectName,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: grades
|
|
|
+ };
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 转换按年级的数据为树形结构(不去重)
|
|
|
+const transformGradeData = (data) => {
|
|
|
+ if (!data || !Array.isArray(data)) return [];
|
|
|
+
|
|
|
+ return data.map(grade => {
|
|
|
+ const classTypes = (grade.classTypePersonVoList || []).map(classType => {
|
|
|
+ const classes = (classType.classInfoPersonVoList || []).map(cls => ({
|
|
|
+ id: `${classType.classType}_${cls.classCode}`,
|
|
|
+ name: cls.className,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: (cls.personVoList || []).map(user => ({
|
|
|
+ id: user.userId,
|
|
|
+ name: user.teacherName,
|
|
|
+ userId: user.userId,
|
|
|
+ userAccount: user.userAccount,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false
|
|
|
+ }))
|
|
|
+ }));
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: `${grade.schoolYearGradeId || grade.gradeCode}_${classType.classType}`,
|
|
|
+ name: classType.classTypeName,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: classes
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: grade.schoolYearGradeId || grade.gradeCode,
|
|
|
+ name: grade.gradeName,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: classTypes
|
|
|
+ };
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 转换按权限的数据为树形结构(不去重)
|
|
|
+const transformPersonalData = (data) => {
|
|
|
+ if (!data || !Array.isArray(data)) return [];
|
|
|
+
|
|
|
+ return data.map(item => {
|
|
|
+ return {
|
|
|
+ id: item.roleId,
|
|
|
+ name: item.roleName,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: (item.personVoList || []).map(user => ({
|
|
|
+ id: user.userId,
|
|
|
+ name: user.teacherName,
|
|
|
+ userId: user.userId,
|
|
|
+ userAccount: user.userAccount,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false
|
|
|
+ }))
|
|
|
+ };
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 转换按学生的数据为树形结构(不去重)
|
|
|
+const transformStudentData = (data) => {
|
|
|
+ if (!data || !Array.isArray(data)) return [];
|
|
|
+
|
|
|
+ return data.map(grade => {
|
|
|
+ const classes = (grade.clsVOS || []).map(cls => ({
|
|
|
+ id: `${grade.schoolYearGradeId || grade.gradeCode}_${cls.classId}`,
|
|
|
+ name: cls.className,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: (cls.studentTblVOS || []).map(student => ({
|
|
|
+ id: student.userId,
|
|
|
+ name: student.studentName,
|
|
|
+ userId: student.userId,
|
|
|
+ userAccount: student.studentCode,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false
|
|
|
+ }))
|
|
|
+ }));
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: `student_${grade.schoolYearGradeId || grade.gradeCode}`,
|
|
|
+ name: grade.gradeName,
|
|
|
+ checked: false,
|
|
|
+ halfChecked: false,
|
|
|
+ children: classes
|
|
|
+ };
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 获取学年
|
|
|
+const getSchoolYear = async () => {
|
|
|
+ try {
|
|
|
+ const res = await overview.findSchoolYear();
|
|
|
+ if (res.data && res.data.length > 0) {
|
|
|
+ schoolYearId.value = res.data[0].id;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取学年失败:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 获取按部门数据
|
|
|
+const loadDepartmentData = async () => {
|
|
|
+ if (!schoolYearId.value) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await overview.find_depart_contain_user({ schoolYearId: schoolYearId.value });
|
|
|
+ fullTreeData.value = transformDepartmentData(res.data);
|
|
|
+ treeData.value = fullTreeData.value;
|
|
|
+ expandedIds.value = [];
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取部门数据失败:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 获取按学科/年级/权限数据
|
|
|
+const loadPersonalData = async (type) => {
|
|
|
+ if (!schoolYearId.value) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await overview.find_collect_personal_info({ schoolYearId: schoolYearId.value });
|
|
|
+
|
|
|
+ let data = [];
|
|
|
+ let transformFn = transformPersonalData;
|
|
|
+
|
|
|
+ if (type === 'subject') {
|
|
|
+ data = res.data.subjectPersonVoList || [];
|
|
|
+ transformFn = transformSubjectData;
|
|
|
+ } else if (type === 'grade') {
|
|
|
+ data = res.data.collectGradePersonVos || [];
|
|
|
+ transformFn = transformGradeData;
|
|
|
+ } else if (type === 'permission') {
|
|
|
+ data = res.data.collectPermissionPersonVos || [];
|
|
|
+ }
|
|
|
+
|
|
|
+ fullTreeData.value = transformFn(data);
|
|
|
+ treeData.value = fullTreeData.value;
|
|
|
+ expandedIds.value = [];
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`获取${type}数据失败:`, error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 获取按学生数据
|
|
|
+const loadStudentData = async () => {
|
|
|
+ if (!schoolYearId.value) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await overview.query_notice_student({ id: 0, schoolYearId: schoolYearId.value });
|
|
|
+ fullTreeData.value = transformStudentData(res.data || []);
|
|
|
+ treeData.value = fullTreeData.value;
|
|
|
+ expandedIds.value = [];
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取学生数据失败:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 切换标签
|
|
|
+const handleTabChange = async (key) => {
|
|
|
+ activeTab.value = key;
|
|
|
+
|
|
|
+ if (key === 'department') {
|
|
|
+ await loadDepartmentData();
|
|
|
+ } else if (key === 'subject' || key === 'grade' || key === 'permission') {
|
|
|
+ await loadPersonalData(key);
|
|
|
+ } else if (key === 'student') {
|
|
|
+ await loadStudentData();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const searchTree = (keyword) => {
|
|
|
+ if (!keyword.trim()) {
|
|
|
+ treeData.value = fullTreeData.value;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const filterNodes = (nodes) => {
|
|
|
+ const filtered = [];
|
|
|
+ nodes.forEach(node => {
|
|
|
+ const hasMatch = node.name && node.name.includes(keyword);
|
|
|
+ let childrenFiltered = [];
|
|
|
+
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ childrenFiltered = filterNodes(node.children);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hasMatch || childrenFiltered.length > 0) {
|
|
|
+ filtered.push({
|
|
|
+ ...node,
|
|
|
+ children: childrenFiltered
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return filtered;
|
|
|
+ };
|
|
|
+
|
|
|
+ treeData.value = filterNodes(fullTreeData.value);
|
|
|
+};
|
|
|
+
|
|
|
+const toggleExpand = ({ itemId, siblingIds, isExpanded }) => {
|
|
|
+ if (isExpanded) {
|
|
|
+ expandedIds.value = expandedIds.value.filter(id => id !== itemId);
|
|
|
+ } else {
|
|
|
+ expandedIds.value = expandedIds.value.filter(id => {
|
|
|
+ if (siblingIds.includes(id)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+ expandedIds.value = [...expandedIds.value, itemId];
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 向下级联:更新所有子节点的选中状态
|
|
|
+const toggleChildren = (children, checked) => {
|
|
|
+ children.forEach(child => {
|
|
|
+ child.checked = checked;
|
|
|
+ child.halfChecked = false;
|
|
|
+ if (child.children && child.children.length > 0) {
|
|
|
+ toggleChildren(child.children, checked);
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 向上级联:更新父节点的选中状态
|
|
|
+const updateParentStatus = () => {
|
|
|
+ const updateNode = (nodes) => {
|
|
|
+ nodes.forEach(node => {
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ updateNode(node.children);
|
|
|
+
|
|
|
+ const childrenChecked = node.children.filter(c => c.checked);
|
|
|
+ const childrenHalfChecked = node.children.filter(c => c.halfChecked);
|
|
|
+
|
|
|
+ if (childrenChecked.length === node.children.length) {
|
|
|
+ node.checked = true;
|
|
|
+ node.halfChecked = false;
|
|
|
+ } else if (childrenChecked.length > 0 || childrenHalfChecked.length > 0) {
|
|
|
+ node.checked = false;
|
|
|
+ node.halfChecked = true;
|
|
|
+ } else {
|
|
|
+ node.checked = false;
|
|
|
+ node.halfChecked = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ updateNode(treeData.value);
|
|
|
+};
|
|
|
+
|
|
|
+const toggleSelect = (item) => {
|
|
|
+ item.checked = !item.checked;
|
|
|
+ item.halfChecked = false;
|
|
|
+
|
|
|
+ if (item.children && item.children.length > 0) {
|
|
|
+ // 向下级联
|
|
|
+ toggleChildren(item.children, item.checked);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 向上级联
|
|
|
+ updateParentStatus();
|
|
|
+};
|
|
|
+
|
|
|
+const selectedCount = computed(() => {
|
|
|
+ let count = 0;
|
|
|
+ const collectChecked = (items) => {
|
|
|
+ items.forEach(item => {
|
|
|
+ if (item.children && item.children.length > 0) {
|
|
|
+ collectChecked(item.children);
|
|
|
+ } else if (item.checked && item.userId) {
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ collectChecked(treeData.value);
|
|
|
+ return count;
|
|
|
+});
|
|
|
+
|
|
|
+const goBack = () => {
|
|
|
+ uni.navigateBack();
|
|
|
+};
|
|
|
+
|
|
|
+const collectSelectedUsers = () => {
|
|
|
+ const selectedUsers = [];
|
|
|
+ const currentTab = activeTab.value;
|
|
|
+
|
|
|
+ const collect = (nodes, parentInfo = {}) => {
|
|
|
+ nodes.forEach(node => {
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ const newParentInfo = { ...parentInfo };
|
|
|
+ if (node.name && !node.userId) {
|
|
|
+ if (currentTab === 'department') {
|
|
|
+ if (!newParentInfo.departmentName) {
|
|
|
+ newParentInfo.departmentName = node.name;
|
|
|
+ } else if (!newParentInfo.groupName) {
|
|
|
+ newParentInfo.groupName = node.name;
|
|
|
+ }
|
|
|
+ } else if (currentTab === 'subject') {
|
|
|
+ if (!newParentInfo.subjectName) {
|
|
|
+ newParentInfo.subjectName = node.name;
|
|
|
+ } else if (!newParentInfo.gradeName) {
|
|
|
+ newParentInfo.gradeName = node.name;
|
|
|
+ }
|
|
|
+ } else if (currentTab === 'grade') {
|
|
|
+ if (!newParentInfo.gradeName) {
|
|
|
+ newParentInfo.gradeName = node.name;
|
|
|
+ } else if (!newParentInfo.classTypeName) {
|
|
|
+ newParentInfo.classTypeName = node.name;
|
|
|
+ } else if (!newParentInfo.className) {
|
|
|
+ newParentInfo.className = node.name;
|
|
|
+ }
|
|
|
+ } else if (currentTab === 'permission') {
|
|
|
+ if (!newParentInfo.roleName) {
|
|
|
+ newParentInfo.roleName = node.name;
|
|
|
+ }
|
|
|
+ } else if (currentTab === 'student') {
|
|
|
+ if (!newParentInfo.gradeName) {
|
|
|
+ newParentInfo.gradeName = node.name;
|
|
|
+ } else if (!newParentInfo.classTypeName) {
|
|
|
+ newParentInfo.classTypeName = node.name;
|
|
|
+ } else if (!newParentInfo.className) {
|
|
|
+ newParentInfo.className = node.name;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ collect(node.children, newParentInfo);
|
|
|
+ } else if (node.checked && node.userId) {
|
|
|
+ selectedUsers.push({
|
|
|
+ id: node.id,
|
|
|
+ name: node.name,
|
|
|
+ userId: node.userId,
|
|
|
+ thirdCode: node.userAccount || '',
|
|
|
+ departmentName: parentInfo.departmentName || '',
|
|
|
+ groupName: parentInfo.groupName || '',
|
|
|
+ subjectName: parentInfo.subjectName || '',
|
|
|
+ gradeName: parentInfo.gradeName || '',
|
|
|
+ classTypeName: parentInfo.classTypeName || '',
|
|
|
+ className: parentInfo.className || '',
|
|
|
+ roleName: parentInfo.roleName || ''
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+ collect(treeData.value);
|
|
|
+ return selectedUsers;
|
|
|
+};
|
|
|
+
|
|
|
+const handleConfirm = () => {
|
|
|
+ const data = {
|
|
|
+ tab: tabs.find(t => t.key === activeTab.value).label,
|
|
|
+ count: selectedCount.value,
|
|
|
+ users: collectSelectedUsers()
|
|
|
+ };
|
|
|
+
|
|
|
+ uni.setStorageSync('selectObjectResult', JSON.stringify(data));
|
|
|
+ uni.navigateBack();
|
|
|
+};
|
|
|
+
|
|
|
+const setSelectedUsers = (users) => {
|
|
|
+ if (!users || !Array.isArray(users)) return;
|
|
|
+
|
|
|
+ const selectedTeacherIds = new Set(users.map(u => u.teacherId));
|
|
|
+
|
|
|
+ const setNode = (nodes) => {
|
|
|
+ nodes.forEach(node => {
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ setNode(node.children);
|
|
|
+ } else if (node.teacherId && selectedTeacherIds.has(node.teacherId)) {
|
|
|
+ node.checked = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ setNode(treeData.value);
|
|
|
+ updateParentStatus();
|
|
|
+};
|
|
|
+
|
|
|
+const setSelectedUsersById = (userIds) => {
|
|
|
+ if (!userIds || !Array.isArray(userIds)) return;
|
|
|
+
|
|
|
+ const selectedIds = new Set(userIds);
|
|
|
+
|
|
|
+ const setNode = (nodes) => {
|
|
|
+ nodes.forEach(node => {
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ setNode(node.children);
|
|
|
+ } else if (node.id && selectedIds.has(node.id)) {
|
|
|
+ node.checked = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ setNode(treeData.value);
|
|
|
+ updateParentStatus();
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(async () => {
|
|
|
+ initSafeArea();
|
|
|
+
|
|
|
+ const pages = getCurrentPages();
|
|
|
+ if (pages.length === 1) {
|
|
|
+ uni.navigateBack();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const lastSelection = uni.getStorageSync('selectObjectLastSelection');
|
|
|
+ if (lastSelection) {
|
|
|
+ try {
|
|
|
+ const data = JSON.parse(lastSelection);
|
|
|
+
|
|
|
+ if (data.isEdit) {
|
|
|
+ editMode.value = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.noticeType) {
|
|
|
+ noticeType.value = data.noticeType;
|
|
|
+ const typeMap = {
|
|
|
+ 1: 'department',
|
|
|
+ 2: 'subject',
|
|
|
+ 3: 'grade',
|
|
|
+ 4: 'permission',
|
|
|
+ 5: 'student'
|
|
|
+ };
|
|
|
+ const tabKey = typeMap[data.noticeType];
|
|
|
+ if (tabKey) {
|
|
|
+ activeTab.value = tabKey;
|
|
|
+ }
|
|
|
+ } else if (data.tab) {
|
|
|
+ const tab = tabs.find(t => t.label === data.tab);
|
|
|
+ if (tab) {
|
|
|
+ activeTab.value = tab.key;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.users) {
|
|
|
+ selectedUserIds.value = data.users.map(u => u.userId || u.id);
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('解析上次选择失败:', e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ await getSchoolYear();
|
|
|
+
|
|
|
+ if (activeTab.value === 'department') {
|
|
|
+ await loadDepartmentData();
|
|
|
+ } else if (activeTab.value === 'subject' || activeTab.value === 'grade' || activeTab.value === 'permission') {
|
|
|
+ await loadPersonalData(activeTab.value);
|
|
|
+ } else if (activeTab.value === 'student') {
|
|
|
+ await loadStudentData();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (selectedUserIds.value.length > 0) {
|
|
|
+ setSelectedUsersById(selectedUserIds.value);
|
|
|
+ } else if (lastSelection) {
|
|
|
+ try {
|
|
|
+ const data = JSON.parse(lastSelection);
|
|
|
+ if (data.users) {
|
|
|
+ setSelectedUsers(data.users);
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('设置选中状态失败:', e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.page_select_object {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ min-height: 100vh;
|
|
|
+}
|
|
|
+
|
|
|
+.tabs_container {
|
|
|
+ position: fixed;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ z-index: 99;
|
|
|
+ display: flex;
|
|
|
+ padding: 24rpx ;
|
|
|
+ background-color: #FFFFFF;
|
|
|
+ justify-content: space-between;
|
|
|
+
|
|
|
+ .tab_item {
|
|
|
+ flex-shrink: 0;
|
|
|
+ width: 122rpx;
|
|
|
+ height: 72rpx;
|
|
|
+ background: #FFFFFF;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ border: 2rpx solid #DCDFE6;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ background: #2E64FA;
|
|
|
+ border-color: #2E64FA;
|
|
|
+
|
|
|
+ .tab_text {
|
|
|
+ color: #FFFFFF;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tab_text {
|
|
|
+ font-weight: 400;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333333;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.disabled {
|
|
|
+ pointer-events: none;
|
|
|
+ opacity: 0.5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.content_list {
|
|
|
+ flex: 1;
|
|
|
+ padding-bottom: 150rpx;
|
|
|
+}
|
|
|
+
|
|
|
+.select_footer {
|
|
|
+ position: fixed;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ padding: 24rpx;
|
|
|
+ background-color: #FFFFFF;
|
|
|
+ border-top: 2rpx solid #F3F3F3;
|
|
|
+
|
|
|
+ .confirm_btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 90rpx;
|
|
|
+ background: #2E64FA;
|
|
|
+ border-radius: 8rpx;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 90rpx;
|
|
|
+
|
|
|
+ .btn_text {
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #FFFFFF;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|