ソースを参照

校内通知问题修改、开发材料采集

吴朋磊 2 週間 前
コミット
fe9bfcc830
78 ファイル変更463 行追加329 行削除
  1. 38 6
      common/request.js
  2. 76 24
      components/commonTabbar.vue
  3. 2 2
      components/nav-bar.vue
  4. 10 10
      components/no-data.vue
  5. 3 3
      components/notice-header.vue
  6. 4 2
      components/page-header.vue
  7. 5 5
      pages/login/index.vue
  8. 24 25
      pages/materialCollection/taskOverview/index.vue
  9. 38 10
      pages/message/index.vue
  10. 1 3
      pages/my/updatePassword.vue
  11. 0 2
      pages/notice/mine/detail.vue
  12. 5 4
      pages/notice/mine/index.vue
  13. 21 14
      pages/notice/overview/index.vue
  14. 45 26
      pages/notice/overview/noticeDetail.vue
  15. 25 18
      pages/notice/publish/index.vue
  16. 17 3
      pages/notice/publish/personList.vue
  17. 18 7
      pages/notice/publish/selectObject.vue
  18. 11 7
      pages/todo/index.vue
  19. 65 85
      pages/workspace/index.vue
  20. 33 55
      pages/workspace/schedule.vue
  21. 2 2
      polyfill.js
  22. BIN
      static/image/materialCollection/shenhe.png
  23. BIN
      static/image/materialCollection/shenheIcon.png
  24. BIN
      static/image/materialCollection/tijiao.png
  25. BIN
      static/image/materialCollection/tijiaoIcon.png
  26. BIN
      static/image/workspace/add.png
  27. 13 7
      store/modules/user.js
  28. 4 1
      tsconfig.json
  29. 1 1
      uni_modules/uni-icons/components/uni-icons/uni-icons.vue
  30. 0 4
      uni_modules/uni-popup/components/uni-popup/uni-popup.vue
  31. 1 1
      unpackage/cache/certdata
  32. 0 1
      unpackage/cache/wgt/__UNI__07352BD/app-config-service.js
  33. 0 0
      unpackage/cache/wgt/__UNI__07352BD/app-service.js
  34. 0 0
      unpackage/cache/wgt/__UNI__07352BD/app.css
  35. BIN
      unpackage/cache/wgt/__UNI__07352BD/assets/uvicons.04d281cc.ttf
  36. 0 0
      unpackage/cache/wgt/__UNI__07352BD/manifest.json
  37. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/login/agreement.css
  38. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/login/index.css
  39. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/materialCollection/reviewMaterial/index.css
  40. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/materialCollection/submitMaterial/index.css
  41. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/materialCollection/taskOverview/index.css
  42. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/message/index.css
  43. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/my/index.css
  44. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/my/updatePassword.css
  45. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/notice/mine/detail.css
  46. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/notice/mine/index.css
  47. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/notice/mine/preview.css
  48. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/notice/overview/index.css
  49. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/notice/overview/noticeDetail.css
  50. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/notice/publish/index.css
  51. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/notice/publish/personList.css
  52. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/notice/publish/selectObject.css
  53. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/studentStudy/index.css
  54. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/studentStudy/learningMonitor/taskDetails.css
  55. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/studentStudy/videoDetails.css
  56. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/teacherHonor/honorOverview/honorTypeDetail.css
  57. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/teacherHonor/index.css
  58. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/teacherStudy/index.css
  59. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/teacherStudy/learningMonitor/taskDetails.css
  60. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/teacherStudy/videoDetails.css
  61. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/todo/index.css
  62. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/workspace/index.css
  63. 0 0
      unpackage/cache/wgt/__UNI__07352BD/pages/workspace/schedule.css
  64. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/icon/delete.png
  65. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/icon/edit.png
  66. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/icon/honor_cup.png
  67. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/icon/honor_seal.png
  68. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorAudit.png
  69. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorAudit_cur.png
  70. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorOverview.png
  71. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorOverview_cur.png
  72. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorTeacher.png
  73. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorTeacher_cur.png
  74. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/myHonor.png
  75. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/myHonor_cur.png
  76. BIN
      unpackage/cache/wgt/__UNI__07352BD/static/image/workspace/add.png
  77. BIN
      unpackage/release/apk/__UNI__07352BD__20260729160304.apk
  78. 1 1
      vite.config.js

+ 38 - 6
common/request.js

@@ -11,6 +11,10 @@ if (process.env.NODE_ENV === 'development') {//本地开发环境
   apiBaseUrl = config.apiBaseUrl
 }
 console.log(process.env.NODE_ENV,apiBaseUrl)
+
+// 防止 401 重复处理的标志
+let isHandling401 = false;
+
 const request = (options) => {
 	if(options.url.endsWith('.js')) return;
 	
@@ -74,14 +78,42 @@ const isLoginPage = () => {
   return currentPage.route === 'pages/login/index';
 };
 
+const clearUserInfoAndRedirect = () => {
+  // 清除用户信息
+  uni.removeStorageSync('token');
+  uni.removeStorageSync('userInfo');
+  uni.removeStorageSync('schoolsList');
+  
+  // 清除store中的信息
+  store.commit('userStore/SET_TOKEN', '');
+  store.commit('userStore/SET_USER_INFO', {});
+  store.commit('userStore/SET_SCHOOLSLIST', '');
+  
+  // 跳转到登录页
+  if (!isLoginPage()) {
+    uni.reLaunch({
+      url: '/pages/login/index'
+    });
+  }
+};
+
 const responseInterceptor = (response) => {
   if (response.data.code === 401) {
-    store.dispatch('logout', true);
-    if (!isLoginPage()) {
-      uni.redirectTo({
-        url: '/pages/login/index'
-      });
+    // 如果已经在处理 401,直接抛出错误,防止重复调用 sign_out
+    if (isHandling401) {
+      throw new Error(response.data.message || '未授权,请重新登录');
     }
+    
+    isHandling401 = true;
+    
+    // 清除用户信息并跳转到登录页
+    clearUserInfoAndRedirect();
+    
+    // 延迟重置标志位,避免连续请求都触发401
+    setTimeout(() => {
+      isHandling401 = false;
+    }, 2000);
+    
     throw new Error(response.data.message || '未授权,请重新登录');
   }
 
@@ -139,4 +171,4 @@ export default {
   post,
   put,
   del
-};
+};

+ 76 - 24
components/commonTabbar.vue

@@ -1,17 +1,25 @@
 <template>
-	<view class="common_tabbar">
-		<view 
-			v-for="(item, idx) in currentTabs" 
-			:key="idx" 
-			class="tabbar_item" 
-			:class="{ active: currentPath === item.path }" 
-			@click="switchTab(item.path)"
-		>
-			<image 
-				:src="currentPath === item.path ? item.selectedIconPath : item.iconPath" 
-				class="tabbar_icon" 
-				mode="aspectFit"
-			></image>
+	<view v-if="currentType === 'home'" class="common_tabbar" :style="{ paddingBottom: 24 + 'rpx' }">
+		<view v-for="(item, idx) in homeTabs" :key="idx" class="tabbar_item"
+			:class="{ active: currentPath === item.path }" @click="switchTab(item.path)">
+			<image :src="currentPath === item.path ? item.selectedIconPath : item.iconPath" class="tabbar_icon"
+				mode="aspectFit"></image>
+			<text class="tabbar_text">{{ item.text }}</text>
+		</view>
+	</view>
+	<view v-else-if="currentType === 'notice'" class="common_tabbar" :style="{ paddingBottom: 24 + 'rpx' }">
+		<view v-for="(item, idx) in noticeTabs" :key="idx" class="tabbar_item"
+			:class="{ active: currentPath === item.path }" @click="switchTab(item.path)">
+			<image :src="currentPath === item.path ? item.selectedIconPath : item.iconPath" class="tabbar_icon"
+				mode="aspectFit"></image>
+			<text class="tabbar_text">{{ item.text }}</text>
+		</view>
+	</view>
+	<view v-else-if="currentType === 'materialCollection'" class="common_tabbar" :style="{ paddingBottom: 24 + 'rpx' }">
+		<view v-for="(item, idx) in materialCollectionTabs" :key="idx" class="tabbar_item"
+			:class="{ active: currentPath === item.path }" @click="switchTab(item.path)">
+			<image :src="currentPath === item.path ? item.selectedIconPath : item.iconPath" class="tabbar_icon"
+				mode="aspectFit"></image>
 			<text class="tabbar_text">{{ item.text }}</text>
 		</view>
 	</view>
@@ -19,10 +27,12 @@
 
 <script setup>
 import { ref, computed, onMounted } from 'vue';
+import { useSafeArea } from '@/common/safeArea';
 
 const currentPath = ref('');
+const { safeAreaBottom, initSafeArea } = useSafeArea();
 
-const workspaceTabs = [
+const homeTabs = [
 	{
 		path: '/pages/workspace/index',
 		iconPath: '/static/image/tabbar/workspace.png',
@@ -40,6 +50,12 @@ const workspaceTabs = [
 		iconPath: '/static/image/tabbar/message.png',
 		selectedIconPath: '/static/image/tabbar/message_cur.png',
 		text: '消息'
+	},
+	{
+		path: '/pages/my/index',
+		iconPath: '/static/image/tabbar/my.png',
+		selectedIconPath: '/static/image/tabbar/my_cur.png',
+		text: '我的'
 	}
 ];
 
@@ -64,11 +80,43 @@ const noticeTabs = [
 	}
 ];
 
-const currentTabs = computed(() => {
+const materialCollectionTabs = [
+	{
+		path: '/pages/materialCollection/taskOverview/index',
+		iconPath: '/static/image/overview/zonglan.png',
+		selectedIconPath: '/static/image/overview/zonglanIcon.png',
+		text: '任务总览'
+	},
+	{
+		path: '/pages/materialCollection/submitMaterial/index',
+		iconPath: '/static/image/materialCollection/tijiao.png',
+		selectedIconPath: '/static/image/materialCollection/tijiaoIcon.png',
+		text: '提交材料'
+	},
+	{
+		path: '/pages/materialCollection/reviewMaterial/index',
+		iconPath: '/static/image/materialCollection/shenhe.png',
+		selectedIconPath: '/static/image/materialCollection/shenheIcon.png',
+		text: '审核材料'
+	}
+];
+
+const currentType = computed(() => {
 	if (currentPath.value.startsWith('/pages/notice/')) {
-		return noticeTabs;
+		return 'notice';
+	}
+	if (currentPath.value.startsWith('/pages/materialCollection/taskOverview/') ||
+		currentPath.value.startsWith('/pages/materialCollection/submitMaterial/') ||
+		currentPath.value.startsWith('/pages/materialCollection/reviewMaterial/')) {
+		return 'materialCollection';
 	}
-	return workspaceTabs;
+	if (currentPath.value.startsWith('/pages/workspace/') ||
+		currentPath.value.startsWith('/pages/todo/') ||
+		currentPath.value.startsWith('/pages/message/') ||
+		currentPath.value.startsWith('/pages/my/')) {
+		return 'home';
+	}
+	return '';
 });
 
 const updateCurrentPath = () => {
@@ -81,14 +129,16 @@ const updateCurrentPath = () => {
 
 const switchTab = (path) => {
 	if (currentPath.value === path) return;
+	if (currentType.value === 'materialCollection') {
+		uni.redirectTo({ url: path });
+		return;
+	}
 	uni.reLaunch({ url: path });
 };
 
 onMounted(() => {
+	initSafeArea();
 	updateCurrentPath();
-	uni.hideTabBar({
-		fail: () => {}
-	});
 });
 </script>
 
@@ -100,9 +150,10 @@ onMounted(() => {
 	right: 0;
 	display: flex;
 	justify-content: space-around;
+	align-items: center;
 	background-color: #FFFFFF;
-	padding: 16rpx 0;
-	padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
+	padding-top: 24rpx;
+	padding-bottom: 24rpx;
 	border-top: 1rpx solid #F0F0F0;
 	box-sizing: border-box;
 	z-index: 999;
@@ -112,10 +163,11 @@ onMounted(() => {
 		flex-direction: column;
 		align-items: center;
 		justify-content: center;
+		padding: 4rpx 16rpx;
 
 		.tabbar_icon {
-			width: 48rpx;
-			height: 48rpx;
+			width: 44rpx;
+			height: 44rpx;
 		}
 
 		.tabbar_text {

+ 2 - 2
components/nav-bar.vue

@@ -148,11 +148,11 @@
 	}
 	const GoBack = () => {
 		if (props.backPath == 'myIndex') {
-			uni.switchTab({
+			uni.redirectTo({
 				url: '/pages/my/index'
 			});
 		} else if (props.backPath == 'workspace') { //跳转工作台
-			uni.switchTab({
+			uni.redirectTo({
 				url: '/pages/workspace/index'
 			});
 		} else {

+ 10 - 10
components/no-data.vue

@@ -6,16 +6,16 @@
 </template>
 
 <script setup>
-const props = defineProps({
-	text:{
-		type: String,
-		default: '暂无数据'
-	},
-	centered:{
-		type: Boolean,
-		default: false
-	}
-})
+	const props = defineProps({
+		text:{
+			type: String,
+			default: '暂无数据'
+		},
+		centered:{
+			type: Boolean,
+			default: false
+		}
+	})
 </script>
 
 <style scoped lang="scss">

+ 3 - 3
components/notice-header.vue

@@ -248,7 +248,7 @@ const handleCreate = () => {
 		display: flex;
 		align-items: center;
 		justify-content: space-between;
-		padding: 24rpx;
+		padding:36rpx 24rpx 24rpx;
 
 		.header_left {
 			display: flex;
@@ -401,8 +401,8 @@ const handleCreate = () => {
 			justify-content: center;
 			gap: 8rpx;
 			.add_icon {
-				width: 32rpx;
-				height: 32rpx;
+				width: 28rpx;
+				height: 28rpx;	
 			}
 			.create_text {
 				color: #FFFFFF;

+ 4 - 2
components/page-header.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="page_header">
+	<view class="page_header" :style="{ paddingTop: 80 + 'rpx' }">
 		<text class="header_title">{{ schoolName }}</text>
 	</view>
 </template>
@@ -7,11 +7,14 @@
 <script setup>
 	import { ref, onMounted } from 'vue';
 	import { useStore } from 'vuex';
+	import { useSafeArea } from '@/common/safeArea';
 
 	const store = useStore();
 	const schoolName = ref('');
+	const { statusBarHeight, initSafeArea } = useSafeArea();
 
 	onMounted(() => {
+		initSafeArea();
 		schoolName.value = store.state.userStore.userInfo.schoolName || '';
 	});
 </script>
@@ -23,7 +26,6 @@
 	left: 0;
 	right: 0;
 	background-color: #FFFFFF;
-	padding-top: calc(26rpx + env(safe-area-inset-top));
 	padding-bottom: 26rpx;
 	padding-left: 24rpx;
 	padding-right: 24rpx;

+ 5 - 5
pages/login/index.vue

@@ -130,10 +130,10 @@ onMounted(() => {
 				uni.setStorageSync('token', token); // 存储 token 到本地
 				store.dispatch('setUserInfo');
 
-				uni.switchTab({
-					url: '/pages/workspace/index'
-				});
-			} else {
+				uni.redirectTo({
+				url: '/pages/workspace/index'
+			});
+		} else {
 				uni.showToast({
 					title: res.msg || '账号不存在或者密码错误!',
 					icon: 'none'
@@ -449,7 +449,7 @@ const LoginSuccess = () => {
 	});
 	store.dispatch('setUserInfo');
 
-	uni.switchTab({
+	uni.redirectTo({
 		url: '/pages/workspace/index'
 	});
 }

+ 24 - 25
pages/materialCollection/taskOverview/index.vue

@@ -19,37 +19,35 @@
 
 		<view class="notice_content">
 			<view class="notice_list">
-				<scroll-view v-if="taskList.length > 0" scroll-y>
-					<view v-for="item in taskList" :key="item.id" class="notice_item">
-						<view class="item_content">
-							<view class="notice_title_row">
-								<image class="notice_icon" :src="item.icon" mode="aspectFit"></image>
-								<text class="notice_title">{{ item.title }}</text>
-							</view>
-							<view class="notice_meta">
-								<view class="status_tag" :class="item.statusClass">
-									<text>{{ item.status }}</text>
-								</view>
-								<text class="meta_text textLength">{{ item.academicYear }}</text>
-								<text class="meta_text textLength">{{ item.category }}</text>
-								<text class="meta_text">{{ item.time }}</text>
-							</view>
+				<scroll-view scroll-y v-for="item in taskList" :key="item.id" class="notice_item">
+					<view class="item_content">
+						<view class="notice_title_row">
+							<image class="notice_icon" :src="item.icon" mode="aspectFit"></image>
+							<text class="notice_title">{{ item.title }}</text>
 						</view>
-						<view class="item_bottom">
-							<view class="notice_stats">
-								<text class="stats_text">提交人: {{ item.submitter }}</text>
-								<text class="stats_text">截止: {{ item.deadline }}</text>
+						<view class="notice_meta">
+							<view class="status_tag" :class="item.statusClass">
+								<text>{{ item.status }}</text>
 							</view>
-							<view class="notice_actions">
-								<view class="action_btn detail" @click="handleDetail(item.id)">
-									<text>详情</text>
-								</view>
+							<text class="meta_text textLength">{{ item.academicYear }}</text>
+							<text class="meta_text textLength">{{ item.category }}</text>
+							<text class="meta_text">{{ item.time }}</text>
+						</view>
+					</view>
+					<view class="item_bottom">
+						<view class="notice_stats">
+							<text class="stats_text">提交人: {{ item.submitter }}</text>
+							<text class="stats_text">截止: {{ item.deadline }}</text>
+						</view>
+						<view class="notice_actions">
+							<view class="action_btn detail" @click="handleDetail(item.id)">
+								<text>详情</text>
 							</view>
 						</view>
 					</view>
 				</scroll-view>
 
-				<no-data v-else centered text="暂无任务" />
+				<no-data v-if="taskList.length === 0" centered text="暂无任务" />
 			</view>
 		</view>
 
@@ -269,8 +267,9 @@ const handleDetail = (id) => {
 				width: 96rpx;
 				text-align: center;
 				line-height: 48rpx;
-				border-radius: 8rpx;
+				border-radius: 4rpx;
 				font-weight: 400;
+				border-radius: 8rpx;
 
 				&.status-pending {
 					background: rgba(46, 100, 250, 0.1);

+ 38 - 10
pages/message/index.vue

@@ -1,12 +1,12 @@
 <template>
-	<view class="page_message">
+	<view class="page_message" :style="{paddingTop: statusBarHeight + 160 + 'rpx', paddingBottom: safeAreaBottom + 150 + 'rpx' }">
 		<page-header></page-header>
 		<view class="message_content">
 			<view class="message_header">
 				<text class="message_title">系统消息({{ unreadCount }}项)</text>
 				<text class="mark_all_read" @click="mark_all_read">全部已读</text>
 			</view>
-			<view class="message_list">
+			<view class="message_list" v-if="messageList.length > 0">
 				<view v-for="item in messageList" :key="item.id" class="message_item">
 					<view class="message_left">
 						<view class="message_info">
@@ -26,7 +26,11 @@
 					</view>
 				</view>
 			</view>
-			<no-data v-if="messageList.length === 0" centered text="暂无系统消息" />
+			<!-- <view v-if="messageList.length === 0" class="schedule_empty">
+				<image src="@/static/image/bg/no_data.png" class="empty_image" mode="aspectFit"></image>
+				<text class="empty_text">暂无系统消息</text>
+			</view> -->
+			<no-data v-if="messageList.length === 0" centered text="暂无系统消息"></no-data>
 		</view>
 		<common-tabbar></common-tabbar>
 	</view>
@@ -37,9 +41,12 @@
 	import { onShow } from '@dcloudio/uni-app';
 	import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
 	import PageHeader from '@/components/page-header.vue';
-	import NoData from '@/components/no-data.vue';
+	import CommonTabbar from '@/components/commonTabbar.vue';
 	import workspace from '@/reqApi/workspace.js';
+	import { useSafeArea } from '@/common/safeArea';
+	import NoData from '@/components/no-data.vue';
 
+	const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
 	const messageList = ref([]);
 	const unreadCount = ref(0);
 	const getTagStyle = (status) => {
@@ -100,6 +107,10 @@
 			console.error('标记所有消息已读失败:', error);
 		}
 	};
+	onMounted(() => {
+		initSafeArea();
+	});
+
 	onShow(() => {
 		fetchMessageList();
 	});
@@ -107,11 +118,10 @@
 
 <style lang="scss">
 .page_message {
-	height: 100vh;
+	min-height: 100vh;
 	display: flex;
 	flex-direction: column;
 	background-color: #FFFFFF;
-	padding-bottom: env(safe-area-inset-bottom);
 	box-sizing: border-box;
 }
 
@@ -120,8 +130,6 @@
 	display: flex;
 	flex-direction: column;
 	overflow: hidden;
-	padding-top: calc(140rpx + env(safe-area-inset-top));
-	padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
 	padding-left: 0rpx;
 	padding-right: 0rpx;
 }
@@ -158,8 +166,6 @@
 	flex: 1;
 	overflow-y: auto;
 	padding:0 24rpx;
-	display: flex;
-	flex-direction: column;
 	.message_item {
 		display: flex;
 		align-items: center;
@@ -260,4 +266,26 @@
 		}
 	}
 }
+
+.schedule_empty {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	font-size: 28rpx;
+	color: #999999;
+	position: relative;
+	height: 100%;
+	overflow: hidden;
+	.empty_image {
+		width: 400rpx;
+		height: 400rpx;
+	}
+
+	.empty_text {
+		position: absolute;
+		bottom: 15%;
+		left: 50%;
+		transform: translate(-50%, -50%);
+	}
+}
 </style>

+ 1 - 3
pages/my/updatePassword.vue

@@ -74,9 +74,7 @@
 	}
 	//返回
 	const GoBack = () => {
-		uni.switchTab({
-			url: '/pages/my/index'
-		});
+		uni.navigateBack();
 	}
 	//修改密码
 	const HandleUpdatePassword = () => {

+ 0 - 2
pages/notice/mine/detail.vue

@@ -112,7 +112,6 @@ const goBack = () => {
 	display: flex;
 	flex-direction: column;
 	background-color: #FFFFFF;
-	padding-bottom: env(safe-area-inset-bottom);
 	box-sizing: border-box;
 }
 
@@ -121,7 +120,6 @@ const goBack = () => {
 	display: flex;
 	flex-direction: column;
 	overflow: hidden;
-	padding-top: calc(140rpx + env(safe-area-inset-top));
 }
 
 .detail_header {

+ 5 - 4
pages/notice/mine/index.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="page_mine">
+	<view class="page_mine" :style="{paddingTop: statusBarHeight + 322 + 'rpx', paddingBottom: safeAreaBottom + 160 + 'rpx' }">
 		<notice-header title="我的通知" :showSearch="true" :showFilter="true" :showTabs="true" :tabs="tabs"
 			:activeTab="activeTab" tabMode="index" @tabChange="handleTabChange" @typeChange="handleTypeChange" @timeChange="handleTimeChange" @searchChange="handleSearchChange"></notice-header>
 
@@ -39,6 +39,9 @@ import { onShow, onLoad } from '@dcloudio/uni-app';
 import NoticeHeader from '@/components/notice-header.vue';
 import NoData from '@/components/no-data.vue';
 import overviewApi from '@/reqApi/overview.js';
+import { useSafeArea } from '@/common/safeArea';
+
+const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
 
 const tabs = ['全部', '未读', '已读'];
 const activeTab = ref(0);
@@ -154,7 +157,6 @@ const handleDetail = (id) => {
 	display: flex;
 	flex-direction: column;
 	background-color: #FFFFFF;
-	padding-bottom: env(safe-area-inset-bottom);
 	box-sizing: border-box;
 }
 
@@ -163,8 +165,7 @@ const handleDetail = (id) => {
 	display: flex;
 	flex-direction: column;
 	overflow: hidden;
-	padding-top: calc(325rpx + env(safe-area-inset-top));
-	padding-bottom: calc(208rpx + env(safe-area-inset-bottom));
+
 	padding-left: 0rpx;
 	padding-right: 0rpx;
 }

+ 21 - 14
pages/notice/overview/index.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="page_notice">
+	<view class="page_notice" :style="{paddingTop: statusBarHeight + 322 + 'rpx', paddingBottom: safeAreaBottom + 160 + 'rpx' }">
 		<notice-header title="校内通知" :showSearch="true" :showFilter="true" :showTabs="true" :tabs="tabs"
 			:activeTab="activeTab" @tabChange="handleTabChange" @typeChange="handleTypeChange"
 			@timeChange="handleTimeChange" @searchChange="handleSearchChange"></notice-header>
@@ -17,8 +17,8 @@
 							<view class="status_tag" :class="item.statusClass">
 								<text>{{ item.status }}</text>
 							</view>
-							<text class="meta_text">{{ item.category }}</text>
-							<text class="meta_text">{{ item.department }}</text>
+							<text class="meta_text textLength">{{ item.category }}</text>
+							<text class="meta_text textLength">{{ item.department }}</text>
 							<text class="meta_text">{{ item.time }}</text>
 						</view>
 					</view>
@@ -43,7 +43,7 @@
 
 				</scroll-view>
 
-				<no-data v-if="noticeList.length === 0" centered text="暂无通知" />
+				<no-data v-if="noticeList.length === 0" text="暂无通知" />
 			</view>
 		</view>
 
@@ -56,13 +56,16 @@
 </template>
 
 <script setup>
-import { ref } from 'vue';
+import { ref, onMounted } from 'vue';
 import { onShow } from '@dcloudio/uni-app';
 import NoticeHeader from '@/components/notice-header.vue';
 import ConfirmModal from '@/components/confirm-modal.vue';
 import overviewApi from '@/reqApi/overview.js';
 import store from '@/store/index.js';
 import NoData from '@/components/no-data.vue';
+import { useSafeArea } from '@/common/safeArea';
+
+const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
 
 const tabs = ['全部', '待发布', '已发布', '已关闭'];
 const activeTab = ref(-1);
@@ -120,6 +123,10 @@ const fetchNoticeList = async () => {
 	}
 };
 
+onMounted(() => {
+	initSafeArea();
+});
+
 onShow(() => {
 	fetchNoticeList();
 });
@@ -191,18 +198,16 @@ const handleDetail = (id) => {
 		uni.showToast({ title: '待发布通知暂无法查看详情', icon: 'none' });
 		return;
 	}
-	const itemStr = encodeURIComponent(JSON.stringify(item));
-	uni.navigateTo({ url: `/pages/notice/overview/noticeDetail?id=${id}&item=${itemStr}` });
+	uni.navigateTo({ url: `/pages/notice/overview/noticeDetail?id=${id}` });
 };
 </script>
 
 <style lang="scss">
 .page_notice {
-	height: 100vh;
+	min-height: 100vh;
 	display: flex;
 	flex-direction: column;
 	background-color: #FFFFFF;
-	padding-bottom: env(safe-area-inset-bottom);
 	box-sizing: border-box;
 }
 
@@ -211,8 +216,6 @@ const handleDetail = (id) => {
 	display: flex;
 	flex-direction: column;
 	overflow: hidden;
-	padding-top: calc(325rpx + env(safe-area-inset-top));
-	padding-bottom: calc(208rpx + env(safe-area-inset-bottom));
 	padding-left: 0rpx;
 	padding-right: 0rpx;
 }
@@ -222,8 +225,6 @@ const handleDetail = (id) => {
 	overflow-y: auto;
 	overflow-x: hidden;
 	padding: 0 24rpx;
-	display: flex;
-	flex-direction: column;
 }
 
 .notice_item {
@@ -294,6 +295,12 @@ const handleDetail = (id) => {
 				color: #999999;
 				line-height: 48rpx;
 			}
+			.textLength {
+					max-width: 160rpx;
+					overflow: hidden;
+					text-overflow: ellipsis;
+					white-space: nowrap;
+				}
 		}
 	}
 
@@ -371,4 +378,4 @@ const handleDetail = (id) => {
 		margin-bottom: 0;
 	}
 }
-</style>
+</style>

+ 45 - 26
pages/notice/overview/noticeDetail.vue

@@ -1,6 +1,6 @@
 <template>
 	<view class="notice_detail">
-		<view class="detail_header" :style="{ paddingTop: statusBarHeight + 'px' }">
+		<view class="detail_header" :style="{ paddingTop: statusBarHeight+64 + 'rpx' }">
 			<uni-icons type="back" size="24" color="#333333" @click="handleBack"></uni-icons>
 			<text class="header_title">通知详情</text>
 			<text class="header_placeholder"></text>
@@ -42,10 +42,10 @@
 				</view>
 
 				<view class="stats_row">
-					<text class="stats_text">共 {{ noticeItem.readCount + noticeItem.unreadCount }} 人</text>
+					<text class="stats_text">共 {{ readerList.length }} 人</text>
 				</view>
 
-				<scroll-view scroll-y class="reader_list">
+				<scroll-view v-if="filteredReaders.length > 0" scroll-y class="reader_list">
 					<view v-for="item in filteredReaders" :key="item.id" class="reader_item">
 						<view class="reader_row reader_row_first">
 							<text class="reader_name">{{ item.name }}</text>
@@ -67,9 +67,9 @@
 							<text v-if="item.readTime" class="reader_detail">{{ item.readTime }}</text>
 						</view>
 					</view>
-
-					<no-data v-if="filteredReaders.length === 0" centered text="暂无数据" />
 				</scroll-view>
+
+				<no-data v-else centered text="暂无数据" />
 			</view>
 		</view>
 	</view>
@@ -77,17 +77,24 @@
 
 <script setup>
 import { ref, computed, onMounted } from 'vue';
+import { onLoad } from '@dcloudio/uni-app';
 import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
 import overviewApi from '@/reqApi/overview.js';
 import NoData from '@/components/no-data.vue';
 import { useSafeArea } from '@/common/safeArea';
 
-const { statusBarHeight, initSafeArea } = useSafeArea();
+const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
 
 const tabs = ['全部', '已读', '未读'];
 const activeTab = ref(0);
 const searchWord = ref('');
-const noticeItem = ref({});
+const noticeItem = ref({
+	title: '',
+	category: '',
+	department: '',
+	time: '',
+	noticeStatus: ''
+});
 const readerList = ref([]);
 const noticeId = ref('');
 
@@ -125,6 +132,27 @@ const filteredReaders = computed(() => {
 	return list;
 });
 
+const fetchNoticeInfo = async () => {
+	if (!noticeId.value) {
+		return;
+	}
+
+	try {
+		const res = await overviewApi.notices_edit({ id: noticeId.value });
+		if (res.data) {
+			noticeItem.value = {
+			title: res.data.noticeName || '',
+			category: res.data.typeName || '',
+			department: res.data.createTeacherName || '',
+			time: res.data.releaseTime || '',
+			noticeStatus: res.data.noticeStatus
+		};
+		}
+	} catch (error) {
+		console.error('获取通知详情失败:', error);
+	}
+};
+
 const fetchReaderList = async () => {
 	try {
 		const readStatusMap = [-1, 1, 0];
@@ -135,7 +163,7 @@ const fetchReaderList = async () => {
 			readStatus: readStatusMap[activeTab.value],
 			word: searchWord.value || ''
 		};
-		const res = await overviewApi.noticeDetail(params);
+		const res = await overviewApi.user_page(params);
 		if (res.data && res.data.records && res.data.records.length > 0 && res.data.records[0].userList) {
 			readerList.value = res.data.records[0].userList;
 		} else {
@@ -172,22 +200,12 @@ const handleBack = () => {
 
 onMounted(() => {
 	initSafeArea();
-	const pages = getCurrentPages();
-	const currentPage = pages[pages.length - 1];
-	const itemStr = currentPage.options?.item;
-	const id = currentPage.options?.id;
-
-	if (itemStr) {
-		try {
-			const item = JSON.parse(decodeURIComponent(itemStr));
-			noticeItem.value = item;
-		} catch (e) {
-			console.error('解析详情数据失败:', e);
-		}
-	}
+});
 
-	if (id) {
-		noticeId.value = id;
+onLoad((options) => {
+	if (options && options.id) {
+		noticeId.value = options.id;
+		fetchNoticeInfo();
 		fetchReaderList();
 	}
 });
@@ -209,10 +227,11 @@ onMounted(() => {
 		display: flex;
 		align-items: center;
 		justify-content: space-between;
-		padding: 24rpx;
+		padding-left: 24rpx;
+		padding-right: 24rpx;
+		padding-bottom: 24rpx;
 		background-color: #FFFFFF;
 		border-bottom: 2rpx solid #F3F3F3;
-		flex-shrink: 0;
 
 		.header_title {
 			font-size: 32rpx;
@@ -442,4 +461,4 @@ onMounted(() => {
 		}
 	}
 }
-</style>
+</style>

+ 25 - 18
pages/notice/publish/index.vue

@@ -1,8 +1,8 @@
 <template>
-	<view class="page_publish">
+	<view class="page_publish" >
 		<common-header :title="isEdit ? '编辑通知' : '发布通知'" @back="goBack"></common-header>
 
-		<scroll-view scroll-y class="publish_content">
+		<scroll-view scroll-y class="publish_content" :style="{ paddingTop: statusBarHeight + 160 + 'rpx', paddingBottom: safeAreaBottom + 'rpx' }">
 			<view class="form_item">
 				<view class="form_row form_row_type">
 					<text class="form_label">通知类型</text>
@@ -99,7 +99,7 @@
 			</view>
 		</scroll-view>
 
-		<view class="publish_footer">
+		<view class="publish_footer" :style="{ paddingBottom: safeAreaBottom + 24 + 'rpx' }">
 			<view class="confirm_btn" @click="handleSave">
 				<text class="btn_text">确定</text>
 			</view>
@@ -109,12 +109,15 @@
 
 <script setup>
 import { ref, reactive, onMounted } from 'vue';
-import { onShow } from '@dcloudio/uni-app';
+import { onLoad, onShow } from '@dcloudio/uni-app';
 import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
 import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue';
 import overviewApi from '@/reqApi/overview.js';
 import CustomRadio from '@/components/customRadio.vue';
 import CommonHeader from '@/components/common-header.vue';
+import { useSafeArea } from '@/common/safeArea';
+
+const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
 
 const showTypePicker = ref(false);
 const publishType = ref(0);
@@ -180,14 +183,16 @@ const fetchNoticeTypeList = async () => {
 };
 
 onMounted(() => {
-	fetchNoticeTypeList();
-	
-	const pages = getCurrentPages();
-	const currentPage = pages[pages.length - 1];
-	if (currentPage.options && currentPage.options.id) {
+	initSafeArea();
+});
+
+onLoad(async (options) => {
+	await fetchNoticeTypeList();
+
+	if (options && options.id) {
 		isEdit.value = true;
-		editId.value = currentPage.options.id;
-		fetchNoticeDetail(currentPage.options.id);
+		editId.value = options.id;
+		fetchNoticeDetail(options.id);
 	}
 });
 
@@ -205,6 +210,9 @@ const fetchNoticeDetail = async (id) => {
 			
 			const typeIndexVal = typeData.value.findIndex(item => item.id === data.typeId);
 			typeIndex.value = typeIndexVal >= 0 ? typeIndexVal : -1;
+			if (typeIndexVal >= 0) {
+				formData.noticeType = typeData.value[typeIndexVal].name;
+			}
 			
 			publishType.value = data.sendTimeType === 2 ? 1 : 0;
 			publishDateTime.value = data.releaseTime || getCurrentDateTime();
@@ -461,15 +469,13 @@ const handleSave = async () => {
 	background-color: #FFFFFF;
 	display: flex;
 	flex-direction: column;
-	padding-bottom: env(safe-area-inset-bottom);
 	box-sizing: border-box;
 }
 
 .publish_content {
 	flex: 1;
 	box-sizing: border-box;
-	padding-top: calc(120rpx + env(safe-area-inset-top));
-	padding-bottom: 158rpx;
+	padding-top: 36rpx;
 	padding-left: 24rpx;
 	padding-right: 24rpx;
 }
@@ -519,14 +525,16 @@ const handleSave = async () => {
 			line-height: 72rpx;
 			background-color: #FFFFFF;
 			border-radius: 8rpx;
-			width: 240rpx;
+			width: 320rpx;
 			border: 2rpx solid #DCDFE6;
 
 			.filter_text {
 				font-size: 28rpx;
 				color: #333333;
 				margin-right: 8rpx;
-
+				overflow: hidden;
+				text-overflow: ellipsis;
+				white-space: nowrap;
 				&.placeholder {
 					color: #909399;
 				}
@@ -701,7 +709,6 @@ const handleSave = async () => {
 
 .publish_footer {
 	padding: 24rpx;
-	padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
 	background-color: #FFFFFF;
 
 	.confirm_btn {
@@ -718,4 +725,4 @@ const handleSave = async () => {
 		}
 	}
 }
-</style>
+</style>

+ 17 - 3
pages/notice/publish/personList.vue

@@ -2,9 +2,9 @@
 	<view class="page_person_list">
 		<CommonHeader :title="headerTitle" @back="goBack"></CommonHeader>
 
-		<SearchBar v-model="searchWord" @search="handleSearch" :isFixed="true" :top="114" :border="false"></SearchBar>
+		<SearchBar v-model="searchWord" @search="handleSearch" :isFixed="true" :top="searchBarTop + 'rpx'" :border="false"></SearchBar>
 
-		<scroll-view scroll-y class="person_list">
+		<scroll-view scroll-y class="person_list" :style="{ paddingTop: contentPaddingTop + 'rpx' }">
 			<view v-for="(person, index) in filteredList" :key="person.userId || person.id" class="person_item">
 				<view class="person_info">
 					<text class="person_name">{{ person.thirdName || person.name }}</text>
@@ -37,6 +37,16 @@ import { ref, computed, onMounted } from 'vue';
 import CommonHeader from '@/components/common-header.vue';
 import SearchBar from '@/components/search-bar.vue';
 import ConfirmModal from '@/components/confirm-modal.vue';
+import { useSafeArea } from '@/common/safeArea';
+
+const { statusBarHeight, initSafeArea } = useSafeArea();
+
+const HEADER_CONTENT_HEIGHT = 174;
+const SEARCHBAR_HEIGHT = 60;
+const SPACING = 24;
+
+const searchBarTop = computed(() => statusBarHeight.value + HEADER_CONTENT_HEIGHT);
+const contentPaddingTop = computed(() => statusBarHeight.value + HEADER_CONTENT_HEIGHT + SEARCHBAR_HEIGHT + SPACING);
 
 const searchWord = ref('');
 
@@ -95,6 +105,8 @@ const goBack = () => {
 };
 
 onMounted(() => {
+	initSafeArea();
+
 	const data = uni.getStorageSync('personListData');
 	if (data) {
 		try {
@@ -124,7 +136,9 @@ onMounted(() => {
 
 .person_list {
 	flex: 1;
-	padding: 222rpx 24rpx 24rpx 24rpx;
+	padding-left: 24rpx;
+	padding-right: 24rpx;
+	padding-bottom: 24rpx;
 	box-sizing: border-box;
 }
 

+ 18 - 7
pages/notice/publish/selectObject.vue

@@ -2,16 +2,16 @@
 	<view class="page_select_object">
 		<CommonHeader title="选择通知对象" @back="goBack"></CommonHeader>
 
-		<view class="tabs_container">
+		<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="212" :zIndex="100"></SearchBar>
+		<SearchBar v-model="searchKeyword" @search="searchTree" :border="true" :isFixed="true" :top="searchBarTop + 'rpx'" :zIndex="100"></SearchBar>
 
-		<scroll-view scroll-y class="content_list">
+		<scroll-view scroll-y class="content_list" :style="{ paddingTop: contentPaddingTop + 'rpx' }">
 			<TreeNode :tree-data="treeData" :expanded-ids="expandedIds" @toggle-expand="toggleExpand"
 				@toggle-select="toggleSelect" />
 		</scroll-view>
@@ -26,11 +26,22 @@
 
 <script setup>
 import { ref, computed, onMounted } from 'vue';
-import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
 import TreeNode from '@/components/tree-node.vue';
 import SearchBar from '@/components/search-bar.vue';
 import CommonHeader from '@/components/common-header.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('');
@@ -587,6 +598,8 @@ const setSelectedUsersById = (userIds) => {
 };
 
 onMounted(async () => {
+	initSafeArea();
+
 	const pages = getCurrentPages();
 	if (pages.length === 1) {
 		uni.redirectTo({ url: '/pages/notice/publish/index' });
@@ -664,7 +677,6 @@ onMounted(async () => {
 
 .tabs_container {
 	position: fixed;
-	top: 96rpx;
 	left: 0;
 	right: 0;
 	z-index: 99;
@@ -708,7 +720,7 @@ onMounted(async () => {
 
 .content_list {
 	flex: 1;
-	padding: 330rpx 0 150rpx 0;
+	padding-bottom: 150rpx;
 }
 
 .select_footer {
@@ -717,7 +729,6 @@ onMounted(async () => {
 	left: 0;
 	right: 0;
 	padding: 24rpx;
-	padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
 	background-color: #FFFFFF;
 	border-top: 2rpx solid #F3F3F3;
 

+ 11 - 7
pages/todo/index.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="page_todo">
+	<view class="page_todo" :style="{ paddingTop: statusBarHeight + 160 + 'rpx', paddingBottom: safeAreaBottom + 150 + 'rpx' }">
 		<page-header></page-header>
 		<view class="todo_content">
 			<!-- 待办事项 -->
@@ -7,7 +7,7 @@
 				<text class="todo_title">待办事项({{ todoList.length }}项)</text>
 			</view>
 			<!-- 待办事项列表 -->
-			<view class="todo_list">
+			<view class="todo_list" v-if="todoList.length > 0">
 				<view v-for="item in todoList" :key="item.id" class="todo_item">
 					<view class="todo_left">
 						<view class="todo_info">
@@ -37,7 +37,7 @@
 					</view>
 				</view>
 			</view>
-			<no-data v-if="todoList.length === 0" centered text="暂无待办事项" />
+			<no-data v-if="todoList.length === 0" centered text="暂无待办事项"></no-data>
 		</view>
 		<common-tabbar></common-tabbar>
 	</view>
@@ -48,9 +48,12 @@
 	import { onShow } from '@dcloudio/uni-app';
 	import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
 	import PageHeader from '@/components/page-header.vue';
+	import CommonTabbar from '@/components/commonTabbar.vue';
 	import NoData from '@/components/no-data.vue';
 	import workspace from '@/reqApi/workspace.js';
+	import { useSafeArea } from '@/common/safeArea';
 
+	const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
 	const todoList = ref([]);
 
 	const getTagStyle = (status) => {
@@ -75,6 +78,10 @@
 		}
 	};
 
+	onMounted(() => {
+		initSafeArea();
+	});
+
 	onShow(() => {
 		fetchTodoList();
 	});
@@ -82,11 +89,10 @@
 
 <style lang="scss">
 .page_todo {
-	height: 100vh;
+	min-height: 100vh;
 	display: flex;
 	flex-direction: column;
 	background-color: #FFFFFF;
-	padding-bottom: env(safe-area-inset-bottom);
 	box-sizing: border-box;
 }
 
@@ -95,8 +101,6 @@
 	display: flex;
 	flex-direction: column;
 	overflow: hidden;
-	padding-top: calc(140rpx + env(safe-area-inset-top));
-	padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
 	padding-left: 0rpx;
 	padding-right: 0rpx;
 }

+ 65 - 85
pages/workspace/index.vue

@@ -1,52 +1,39 @@
 <template>
-	<view class="page_workspace">
+	<view class="page_workspace"
+		:style="{ paddingTop: statusBarHeight + 160 + 'rpx', paddingBottom: safeAreaBottom + 150 + 'rpx' }">
 		<page-header></page-header>
 		<scroll-view scroll-y class="workspace_content">
 			<!-- 系统列表 -->
 			<view class="system_list">
-				<view class="section_title">系统列表</view>
-				
 				<template v-if="largeCard?.visible">
 					<view class="system_grid_with_large">
 						<view class="large_card" @click="handleSystemClick(largeCard)">
 							<image :src="largeCard.image" class="large_icon" mode="aspectFit"></image>
 							<text class="large_name">{{ largeCard.name }}</text>
 						</view>
-						
+
 						<view class="right_top_grid">
-							<view 
-								v-for="(item, index) in rightTopCards" 
-								:key="index" 
-								class="small_item"
-								@click="handleSystemClick(item)"
-							>
+							<view v-for="(item, index) in rightTopCards" :key="index" class="small_item"
+								@click="handleSystemClick(item)">
 								<image :src="item.image" class="small_icon" mode="aspectFit"></image>
 								<text class="small_name">{{ item.name }}</text>
 							</view>
 						</view>
 					</view>
-					
+
 					<view class="bottom_grid">
-						<view 
-							v-for="(item, index) in bottomCards" 
-							:key="index" 
-							class="small_item"
-							@click="handleSystemClick(item)"
-						>
+						<view v-for="(item, index) in bottomCards" :key="index" class="small_item"
+							@click="handleSystemClick(item)">
 							<image :src="item.image" class="small_icon" mode="aspectFit"></image>
 							<text class="small_name">{{ item.name }}</text>
 						</view>
 					</view>
 				</template>
-				
+
 				<template v-else>
 					<view class="system_grid_full">
-						<view 
-							v-for="(item, index) in allSmallCards" 
-							:key="index" 
-							class="small_item"
-							@click="handleSystemClick(item)"
-						>
+						<view v-for="(item, index) in allSmallCards" :key="index" class="small_item"
+							@click="handleSystemClick(item)">
 							<image :src="item.image" class="small_icon" mode="aspectFit"></image>
 							<text class="small_name">{{ item.name }}</text>
 						</view>
@@ -95,7 +82,8 @@
 					</view>
 					<view class="calendar_days">
 						<view v-for="day in calendarDays" :key="day.fullDate" class="day_item"
-							:class="{ active: day.isActive, weekend: day.isWeekend, today: day.isToday }" @click="handleDayClick(day)">
+							:class="{ active: day.isActive, weekend: day.isWeekend, today: day.isToday }"
+							@click="handleDayClick(day)">
 							<text class="day_text">{{ day.date }}</text>
 							<view class="schedule_dot" :class="{ visible: day.hasSchedule }"></view>
 						</view>
@@ -104,21 +92,12 @@
 				<!-- 日程列表 -->
 				<view class="schedule_list">
 					<view class="schedule_title">当日日程</view>
-					<no-data v-if="scheduleList.length === 0" centered text="暂无日程安排" />
-					<view 
-						v-else 
-						v-for="item in scheduleList" 
-						:key="item.id" 
-						class="schedule_item"
-					>
+					<no-data v-if="scheduleList.length === 0" text="暂无日程安排" />
+					<view v-else v-for="item in scheduleList" :key="item.id" class="schedule_item">
 						<view class="schedule_dot"></view>
 						<view class="schedule_text_container">
-							<text class="schedule_text" :class="{ expanded: expandedItems[item.id] }">{{ item.title }}</text>
-							<text 
-								v-if="item.title.length > 30" 
-								class="toggle_text" 
-								@click.stop="toggleExpand(item.id)"
-							>{{ expandedItems[item.id] ? '收起' : '更多' }}</text>
+							<text class="schedule_text" :class="{ expanded: expandedItems[item.id] }">{{ item.title
+								}}</text>
 						</view>
 					</view>
 				</view>
@@ -138,13 +117,10 @@
 					</view>
 				</view>
 				<view class="modal-body">
-					<text class="modal-date">{{ currentYear }}-{{ String(currentMonth).padStart(2, '0') }}-{{ String(currentDay).padStart(2, '0') }}日程</text>
-					<textarea 
-						class="schedule-textarea" 
-						v-model="scheduleContent" 
-						placeholder="请输入日程内容"
-						placeholder-class="textarea-placeholder"
-					></textarea>
+					<text class="modal-date">{{ currentYear }}-{{ String(currentMonth).padStart(2, '0') }}-{{
+						String(currentDay).padStart(2, '0') }}日程</text>
+					<textarea class="schedule-textarea" v-model="scheduleContent" placeholder="请输入日程内容"
+						placeholder-class="textarea-placeholder"></textarea>
 				</view>
 				<view class="modal-footer">
 					<view class="modal-btn cancel-btn" @click="handleCloseModal">
@@ -167,24 +143,27 @@ import { useStore } from 'vuex';
 import workspaceApi from '@/reqApi/workspace.js';
 import PageHeader from '@/components/page-header.vue';
 import NoData from '@/components/no-data.vue';
+import CommonTabbar from '@/components/commonTabbar.vue';
+import { useSafeArea } from '@/common/safeArea';
 
 const store = useStore();
 const schoolName = ref('');
+const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
 
 const systemItems = ref([
-	{ name: '大数据精准教学诊断平台', key:'', image: '/static/image/workspace/iconLeft.png', isLarge: true, visible: true },
-	{ name: '选择题判分', key:'', image: '/static/image/workspace/icon1.png', isLarge: false, visible: true },
-	{ name: '材料采集', key:'materialCollection', image: '/static/image/workspace/icon2.png', isLarge: false, visible: true },
-	{ name: '教师研修', key:'teacherStudy', image: '/static/image/workspace/icon3.png', isLarge: false, visible: true },
-	{ name: '学生学习', key:'studentStudy', image: '/static/image/workspace/icon4.png', isLarge: false, visible: true },
-	{ name: '智能选课', key:'', image: '/static/image/workspace/icon5.png', isLarge: false, visible: true },
-	{ name: '教师发展', key:'teacherHonor', image: '/static/image/workspace/icon6.png', isLarge: false, visible: true },
-	{ name: '协同备课', key:'', image: '/static/image/workspace/icon7.png', isLarge: false, visible: true },
-	{ name: '校内通知', key:'notice', image: '/static/image/workspace/icon8.png', isLarge: false, visible: true },
-	{ name: '评教评学', key:'', image: '/static/image/workspace/icon9.png', isLarge: false, visible: true },
-	{ name: '考场编排', key:'', image: '/static/image/workspace/icon10.png', isLarge: false, visible: true },
-	{ name: '听课评课', key:'', image: '/static/image/workspace/icon11.png', isLarge: false, visible: true },
-	{ name: '基础数据', key:'', image: '/static/image/workspace/icon12.png', isLarge: false, visible: true }
+	{ name: '大数据精准教学诊断平台', key: '', image: '/static/image/workspace/iconLeft.png', isLarge: true, visible: true },
+	{ name: '选择题判分', key: '', image: '/static/image/workspace/icon1.png', isLarge: false, visible: true },
+	{ name: '材料采集', key: 'materialCollection', image: '/static/image/workspace/icon2.png', isLarge: false, visible: true },
+	{ name: '教师研修', key: 'teacherStudy', image: '/static/image/workspace/icon3.png', isLarge: false, visible: true },
+	{ name: '学生学习', key: 'studentStudy', image: '/static/image/workspace/icon4.png', isLarge: false, visible: true },
+	{ name: '智能选课', key: '', image: '/static/image/workspace/icon5.png', isLarge: false, visible: true },
+	{ name: '教师发展', key: '', image: '/static/image/workspace/icon6.png', isLarge: false, visible: true },
+	{ name: '协同备课', key: '', image: '/static/image/workspace/icon7.png', isLarge: false, visible: true },
+	{ name: '校内通知', key: 'notice', image: '/static/image/workspace/icon8.png', isLarge: false, visible: true },
+	{ name: '评教评学', key: '', image: '/static/image/workspace/icon9.png', isLarge: false, visible: true },
+	{ name: '考场编排', key: '', image: '/static/image/workspace/icon10.png', isLarge: false, visible: true },
+	{ name: '听课评课', key: '', image: '/static/image/workspace/icon11.png', isLarge: false, visible: true },
+	{ name: '基础数据', key: '', image: '/static/image/workspace/icon12.png', isLarge: false, visible: true }
 ]);
 
 const largeCard = computed(() => systemItems.value.find(item => item.isLarge));
@@ -262,12 +241,12 @@ const getWeekRange = (date) => {
 const updateCalendarDays = () => {
 	const days = [];
 	const { monday } = getWeekRange(new Date(currentYear.value, currentMonth.value - 1, currentDay.value));
-	
+
 	weekStartDate.value = monday;
 	const sunday = new Date(monday);
 	sunday.setDate(monday.getDate() + 6);
 	weekEndDate.value = sunday;
-	
+
 	for (let i = 0; i < 7; i++) {
 		const date = new Date(monday);
 		date.setDate(monday.getDate() + i);
@@ -291,7 +270,7 @@ const fetchScheduleList = async () => {
 	const { monday, sunday } = getWeekRange(new Date(currentYear.value, currentMonth.value - 1, currentDay.value));
 	const startDate = `${monday.getFullYear()}-${String(monday.getMonth() + 1).padStart(2, '0')}-${String(monday.getDate()).padStart(2, '0')}`;
 	const endDate = `${sunday.getFullYear()}-${String(sunday.getMonth() + 1).padStart(2, '0')}-${String(sunday.getDate()).padStart(2, '0')}`;
-	
+
 	isLoading.value = true;
 	try {
 		const res = await workspaceApi.getSchedule({ startDate, endDate });
@@ -324,6 +303,7 @@ const updateYearMonthIndex = () => {
 };
 
 onMounted(() => {
+	initSafeArea();
 	schoolName.value = store.state.userStore.userInfo.schoolName || '';
 	generateYearList();
 	generateMonthList();
@@ -340,7 +320,7 @@ const handleSystemClick = (item) => {
 		const userInfo = store.state.userStore.userInfo || uni.getStorageSync('userInfo') || {};
 		const roleCodes = userInfo.roleCodes || [];
 		const isSchoolManager = Array.isArray(roleCodes) && roleCodes.includes('SCHOOL_MANAGER');
-		
+
 		if (isSchoolManager) {
 			uni.navigateTo({
 				url: '/pages/notice/overview/index'
@@ -350,13 +330,17 @@ const handleSystemClick = (item) => {
 				url: '/pages/notice/mine/index?hideTabbar=true'
 			});
 		}
-	} else if(item.key === 'materialCollection'){
+	} else if (item.key === 'materialCollection') {
 		uni.navigateTo({
 			url: '/pages/materialCollection/taskOverview/index'
 		});
-	} else if(item.key == 'teacherStudy' || item.key == 'studentStudy' || item.key == 'teacherHonor'){//教师研修 学生学习 教师发展
+	} else if (item.key == 'teacherStudy') {//教师研修
+		uni.navigateTo({
+			url: '/pages/teacherStudy/index'
+		});
+	} else if (item.key == 'studentStudy') {//学生学习
 		uni.navigateTo({
-			url: `/pages/${item.key}/index`
+			url: '/pages/studentStudy/index'
 		});
 	} else {
 		uni.showToast({ title: `即将打开:${item.name}`, icon: 'none' });
@@ -364,7 +348,7 @@ const handleSystemClick = (item) => {
 };
 
 const handleViewSchedule = () => {
-	uni.navigateTo({	
+	uni.navigateTo({
 		url: '/pages/workspace/schedule'
 	});
 };
@@ -512,16 +496,13 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 .page_workspace {
 	min-height: 100vh;
 	background-color: #F8F9FD;
-	padding-bottom: env(safe-area-inset-bottom);
 	box-sizing: border-box;
 }
 
 .workspace_content {
-	padding-top: calc(140rpx + env(safe-area-inset-top));
-	padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
 	padding-left: 24rpx;
 	padding-right: 24rpx;
-	height: 100vh;
+	height: 100%;
 	box-sizing: border-box;
 	overflow: hidden;
 }
@@ -794,7 +775,7 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 					height: 8rpx;
 					background-color: transparent;
 					border-radius: 50%;
-					
+
 					&.visible {
 						background-color: #2E64FA;
 					}
@@ -808,9 +789,7 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 		background: #F9FAFF;
 		border-radius: 20rpx 20rpx 20rpx 20rpx;
 		padding: $spacing-lg;
-		display: flex;
-		flex-direction: column;
-		flex: 1;
+
 		.schedule_title {
 			font-size: 28rpx;
 			font-weight: 500;
@@ -848,24 +827,23 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 				color: #666666;
 				line-height: 1.6;
 				display: -webkit-box;
-				-webkit-box-orient: vertical;
-				-webkit-line-clamp: 2;
-				overflow: hidden;
-				text-overflow: ellipsis;
-
+				flex: 1;
+				text-align: justify;
 				&.expanded {
 					-webkit-line-clamp: unset;
 					overflow: visible;
 					text-overflow: unset;
+					padding-right: 0;
 				}
 			}
 
 			.toggle_text {
-				font-size: 24rpx;
+				font-size: 28rpx;
 				color: #2E64FA;
-				float: right;
-				margin-top: 14rpx;
-				display: inline;
+				position: absolute;
+				right: 0;
+				bottom: 0;
+				line-height: 1.6;
 			}
 		}
 	}
@@ -875,7 +853,8 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 		gap: 16rpx;
 		height: 56rpx;
 		background-color: #FFFFFF;
-		border-radius: 12rpx 12rpx 12rpx 12rpx;;
+		border-radius: 12rpx 12rpx 12rpx 12rpx;
+		;
 		border: 1px solid #2E64FA;
 
 		.btn_text {
@@ -971,6 +950,7 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 		padding: 28rpx 40rpx;
 		gap: 16rpx;
 		border-top: 2rpx solid #EBEEF5;
+
 		.modal-btn {
 			height: 72rpx;
 			// padding: 0 48rpx;
@@ -997,4 +977,4 @@ $shadow-sm: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
 		}
 	}
 }
-</style>
+</style>

+ 33 - 55
pages/workspace/schedule.vue

@@ -1,13 +1,14 @@
 <template>
-	<view class="page">
+	<view class="page" :style="{ paddingTop: statusBarHeight + 140 + 'rpx', paddingBottom: safeAreaBottom + 'rpx' }">
 		<!-- 导航栏 -->
-		<view class="nav_bar">
+		 <common-header :title="'校历安排'" @back="handleBack"></common-header>
+		<!-- <view class="nav_bar" :style="{ paddingTop: statusBarHeight + 24 + 'rpx' }">
 			<view class="nav_back" @click="handleBack">
 				<uni-icons type="back" size="26" color="#333333"></uni-icons>
 			</view>
 			<text class="nav_title">校历安排</text>
 			<view class="nav_right"></view>
-		</view>
+		</view> -->
 		<!-- 日历 -->
 		<view class="calendar_container">
 			<view class="calendar_header">
@@ -44,26 +45,19 @@
 			<view class="schedule_header">
 				<text class="schedule_date">{{ selectedDate }}</text>
 				<view class="add_btn" @click="handleAddSchedule">
+					<!-- <uni-icons type="‌plus-filled" size="24" color="#fff"></uni-icons> -->
 					<image src="/static/image/workspace/add.png" class="add_icon" mode="aspectFit"></image>
 					<text>新增日程</text>
 				</view>
 			</view>
 
-			<view v-if="currentScheduleList.length === 0" class="schedule_empty">
-				<image src="@/static/image/bg/no_data.png" class="empty_image" mode="aspectFit"></image>
-				<text class="empty_text">暂无日程安排</text>
-			</view>
+			<no-data v-if="currentScheduleList.length === 0" centered text="暂无日程安排"></no-data>
 
 			<view v-else class="schedule_list">
 				<view v-for="item in currentScheduleList" :key="item.id" class="schedule_item">
 					<view class="schedule_dot"></view>
 					<view class="schedule_text_container">
 						<text class="schedule_text" :class="{ expanded: expandedItems[item.id] }">{{ item.title }}</text>
-						<text 
-							v-if="item.title.length > 30" 
-							class="toggle_text" 
-							@click.stop="toggleExpand(item.id)"
-						>{{ expandedItems[item.id] ? '收起' : '更多' }}</text>
 					</view>
 					<view class="schedule_actions">
 						<text class="action_btn delete" @click="handleDelete(item.id)">删除</text>
@@ -101,6 +95,12 @@
 <script setup lang="ts">
 import { ref, computed, onMounted } from 'vue';
 import workspaceApi from '@/reqApi/workspace';
+import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
+import { useSafeArea } from '@/common/safeArea';
+import commonHeader from '@/components/common-header.vue';
+import NoData from '@/components/no-data.vue';
+
+const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
 
 interface CalendarDay {
 	date: number;
@@ -259,7 +259,7 @@ const handleDateChange = (e: { detail: { value: string } }) => {
 };
 
 const handleBack = () => {
-	uni.switchTab({
+	uni.redirectTo({
 		url: '/pages/workspace/index'
 	});
 };
@@ -331,16 +331,18 @@ const handleConfirmSchedule = async () => {
 };
 
 onMounted(() => {
+	initSafeArea();
 	fetchScheduleList();
 });
 </script>
 
 <style lang="scss" scoped>
 .page {
-	height: 100vh;
+	min-height: 100vh;
 	background-color: #F5F7FA;
-	padding-bottom: env(safe-area-inset-bottom);
 	box-sizing: border-box;
+	display: flex;
+	flex-direction: column;
 }
 
 .nav_bar {
@@ -348,7 +350,6 @@ onMounted(() => {
 	display: flex;
 	align-items: center;
 	justify-content: space-between;
-	padding-top: calc(24rpx + env(safe-area-inset-top));
 	padding-bottom: 24rpx;
 	padding-left: 24rpx;
 	padding-right: 24rpx;
@@ -378,6 +379,7 @@ onMounted(() => {
 	margin: 16rpx;
 	border-radius: 20rpx;
 	padding: 16rpx;
+	flex-shrink: 0;
 
 	.calendar_header {
 		display: flex;
@@ -476,7 +478,7 @@ onMounted(() => {
 			}
 
 			&.today:not(.active) .day_num {
-				border-color: #2E64FA;
+				color: #2E64FA;
 			}
 		}
 	}
@@ -487,6 +489,10 @@ onMounted(() => {
 	margin: 0 16rpx 16rpx;
 	border-radius: 16rpx;
 	padding: 24rpx;
+	display: flex;
+	flex-direction: column;
+	flex: 1;
+	overflow: hidden;
 
 	.schedule_header {
 		display: flex;
@@ -495,6 +501,7 @@ onMounted(() => {
 		margin-bottom: 24rpx;
 		padding-bottom: 32rpx;
 		border-bottom: 2rpx solid #EBEEF5;
+		flex-shrink: 0;
 
 		.schedule_date {
 			font-size: 36rpx;
@@ -519,31 +526,12 @@ onMounted(() => {
 		}
 	}
 
-	.schedule_empty {
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		font-size: 28rpx;
-		color: #999999;
-		position: relative;
-
-		.empty_image {
-			width: 400rpx;
-			height: 400rpx;
-		}
-
-		.empty_text {
-			position: absolute;
-			bottom: 15%;
-			left: 50%;
-			transform: translate(-50%, -50%);
-		}
-	}
-
 	.schedule_list {
+		flex: 1;
+		overflow-y: auto;
 		.schedule_item {
 			display: flex;
-			align-items: center;
+			align-items: flex-start;
 			padding: 20rpx 0;
 			border-bottom: 2rpx solid #EBEEF5;
 
@@ -558,6 +546,7 @@ onMounted(() => {
 				border-radius: 50%;
 				margin-right: 16rpx;
 				flex-shrink: 0;
+				margin-top:16rpx
 			}
 
 			.schedule_text_container {
@@ -570,35 +559,24 @@ onMounted(() => {
 				color: #666666;
 				line-height: 1.6;
 				display: -webkit-box;
-				-webkit-box-orient: vertical;
-				-webkit-line-clamp: 2;
-				overflow: hidden;
-				text-overflow: ellipsis;
-
+				text-align: justify;
+				flex: 1;
 				&.expanded {
 					-webkit-line-clamp: unset;
 					overflow: visible;
 					text-overflow: unset;
+					padding-right: 0;
 				}
 			}
 
-			.toggle_text {
-				font-size: 24rpx;
-				color: #2E64FA;
-				position: absolute;
-				right: 0;
-				bottom: 0;
-				line-height: 1.6;
-				background-color: #FFFFFF;
-				padding-left: 10rpx;
-			}
 
 			.schedule_actions {
 				display: flex;
 				gap: 24rpx;
 				margin-left: 36rpx;
+				line-height: 1.6;
 				.action_btn {
-					font-size: 26rpx;
+					font-size: 28rpx;
 
 					&.delete {
 						color: #F56C6C;

+ 2 - 2
polyfill.js

@@ -1,5 +1,5 @@
-// #ifdef MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
-// 小程序环境 Vue Devtools 兼容处理
+// #ifdef MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-BAIDU || APP-PLUS
+// 小程序/App环境 Vue Devtools 兼容处理
 (function() {
   try {
     // Vue 内部 getDevtoolsGlobalHook 会获取全局对象

BIN
static/image/materialCollection/shenhe.png


BIN
static/image/materialCollection/shenheIcon.png


BIN
static/image/materialCollection/tijiao.png


BIN
static/image/materialCollection/tijiaoIcon.png


BIN
static/image/workspace/add.png


+ 13 - 7
store/modules/user.js

@@ -21,11 +21,12 @@ const userStore = {
 		//退出登录
 		LOGOUT_USERINFO(state)
 		{
-			uni.clearStorageSync();
-			// state.userInfo={};
-			// state.token="";
-			// uni.setStorageSync('token',"");
-			// uni.setStorageSync('userInfo', {});
+			state.token = '';
+			state.userInfo = {};
+			state.schoolsList = '';
+			uni.removeStorageSync('token');
+			uni.removeStorageSync('userInfo');
+			uni.removeStorageSync('schoolsList');
 		},
 		//保存学校
 		SET_SCHOOLSLIST(state,list){
@@ -47,8 +48,13 @@ const userStore = {
 		//注销退出登录
 		async logout({commit},isOut){
 			if(isOut){
-				const res = await userApi.signOut();
-				if (res.code === 200) {
+				try {
+					const res = await userApi.signOut();
+					if (res.code === 200) {
+						commit('LOGOUT_USERINFO');
+					}
+				} catch (error) {
+					// signOut 失败(如token无效),直接清除本地数据
 					commit('LOGOUT_USERINFO');
 				}
 			}else{

+ 4 - 1
tsconfig.json

@@ -4,7 +4,7 @@
 		"useDefineForClassFields": true,
 		"module": "ESNext",
 		"moduleResolution": "bundler",
-		"strict": true,
+		"strict": false,
 		"jsx": "preserve",
 		"resolveJsonModule": true,
 		"isolatedModules": true,
@@ -12,12 +12,15 @@
 		"lib": ["ESNext", "DOM"],
 		"skipLibCheck": true,
 		"noEmit": true,
+		"allowJs": true,
+		"checkJs": false,
 		"paths": {
 			"@/*": ["./*"]
 		},
 		"types": ["@dcloudio/types"]
 	},
 	"include": [
+		"env.d.ts",
 		"src/**/*.ts",
 		"src/**/*.d.ts",
 		"src/**/*.tsx",

+ 1 - 1
uni_modules/uni-icons/components/uni-icons/uni-icons.vue

@@ -91,4 +91,4 @@
 		text-decoration: none;
 		text-align: center;
 	}
-</style>
+</style>

+ 0 - 4
uni_modules/uni-popup/components/uni-popup/uni-popup.vue

@@ -490,10 +490,6 @@
 			position: relative;
 
 			/* iphonex 等安全区设置,底部安全区适配 */
-			/* #ifndef APP-NVUE */
-			// padding-bottom: constant(safe-area-inset-bottom);
-			// padding-bottom: env(safe-area-inset-bottom);
-			/* #endif */
 			&.left,
 			&.right {
 				/* #ifdef H5 */

+ 1 - 1
unpackage/cache/certdata

@@ -1,4 +1,4 @@
-andrCertfile=C:/jdk-21/bin/workApp.keystore
+andrCertfile=D:/Hbuild X/HBuilderX/bin/workApp.keystore
 andrCertAlias=hjyWorkAppkey
 andrCertPass=l652FwqegF0KViqLH3Mk+w==
 storePassword=l652FwqegF0KViqLH3Mk+w==

ファイルの差分が大きいため隠しています
+ 0 - 1
unpackage/cache/wgt/__UNI__07352BD/app-config-service.js


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/app-service.js


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/app.css


BIN
unpackage/cache/wgt/__UNI__07352BD/assets/uvicons.04d281cc.ttf


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/manifest.json


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/login/agreement.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/login/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/materialCollection/reviewMaterial/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/materialCollection/submitMaterial/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/materialCollection/taskOverview/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/message/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/my/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/my/updatePassword.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/notice/mine/detail.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/notice/mine/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/notice/mine/preview.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/notice/overview/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/notice/overview/noticeDetail.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/notice/publish/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/notice/publish/personList.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/notice/publish/selectObject.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/studentStudy/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/studentStudy/learningMonitor/taskDetails.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/studentStudy/videoDetails.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/teacherHonor/honorOverview/honorTypeDetail.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/teacherHonor/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/teacherStudy/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/teacherStudy/learningMonitor/taskDetails.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/teacherStudy/videoDetails.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/todo/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/workspace/index.css


ファイルの差分が大きいため隠しています
+ 0 - 0
unpackage/cache/wgt/__UNI__07352BD/pages/workspace/schedule.css


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/icon/delete.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/icon/edit.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/icon/honor_cup.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/icon/honor_seal.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorAudit.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorAudit_cur.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorOverview.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorOverview_cur.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorTeacher.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/honorTeacher_cur.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/myHonor.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/tabbar/myHonor_cur.png


BIN
unpackage/cache/wgt/__UNI__07352BD/static/image/workspace/add.png


BIN
unpackage/release/apk/__UNI__07352BD__20260727152326.apk → unpackage/release/apk/__UNI__07352BD__20260729160304.apk


+ 1 - 1
vite.config.js

@@ -7,7 +7,7 @@ const define = {
 	__VUE_PROD_DEVTOOLS__: 'false'
 }
 if (!["mp-weixin", "h5", "web"].includes(process.env.UNI_PLATFORM)) {
-	define['global'] = null
+	define['global'] = '{}'
 	define['wx'] = 'uni'
 }
 export default defineConfig({

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません