1
0

2 Revīzijas 240ab0b635 ... dd0c73bdc7

Autors SHA1 Ziņojums Datums
  liurongli dd0c73bdc7 材料采集 1 nedēļu atpakaļ
  liurongli 7290e7a583 材料采集 1 nedēļu atpakaļ
37 mainītis faili ar 2188 papildinājumiem un 733 dzēšanām
  1. 1 1
      common/common.js
  2. 2 2
      components/confirmModal.vue
  3. 15 12
      components/navBar.vue
  4. 2 2
      components/noticeHeader.vue
  5. 2 2
      components/popupDialog.vue
  6. 1 1
      components/searchBar.vue
  7. 2 2
      components/treeNode.vue
  8. 2 2
      components/treeNodeNoDedup.vue
  9. 11 4
      pages.json
  10. 5 4
      pages/login/agreement.vue
  11. 44 6
      pages/login/index.vue
  12. 73 0
      pages/materialCollection/index.vue
  13. 321 227
      pages/materialCollection/reviewMaterial/index.vue
  14. 320 224
      pages/materialCollection/submitMaterial/index.vue
  15. 384 0
      pages/materialCollection/taskOverview/addEdit.vue
  16. 6 6
      pages/materialCollection/taskOverview/components/index.vue
  17. 319 184
      pages/materialCollection/taskOverview/index.vue
  18. 594 0
      pages/materialCollection/taskOverview/taskDetail.vue
  19. 1 1
      pages/message/index.vue
  20. 1 1
      pages/notice/mine/detail.vue
  21. 1 1
      pages/notice/mine/index.vue
  22. 1 1
      pages/notice/overview/noticeDetail.vue
  23. 1 1
      pages/studentStudy/index.vue
  24. 4 4
      pages/studentStudy/learningMonitor/taskDetails.vue
  25. 0 1
      pages/studentStudy/myLearning/index.vue
  26. 1 1
      pages/teacherHonor/honorAudit/teacherDetail.vue
  27. 2 2
      pages/teacherHonor/honorOverview/honorTypeAuditDetail.vue
  28. 1 1
      pages/teacherHonor/honorOverview/honorTypeDetail.vue
  29. 2 2
      pages/teacherHonor/honorOverview/index.vue
  30. 1 1
      pages/teacherHonor/index.vue
  31. 1 1
      pages/teacherStudy/index.vue
  32. 4 4
      pages/teacherStudy/learningMonitor/taskDetails.vue
  33. 3 7
      pages/workspace/index.vue
  34. 2 2
      pages/workspace/schedule.vue
  35. 51 23
      reqApi/notification.js
  36. BIN
      static/image/icon/CursorUserSetup-x64-3.15.6.exe
  37. 7 0
      style/common.scss

+ 1 - 1
common/common.js

@@ -139,7 +139,7 @@ export function remainingDays(endTime) {
     // 4) 计算天数差并 +1(含当天和结束天)
     // 4) 计算天数差并 +1(含当天和结束天)
     const diffDays = Math.round((endStart.getTime() - todayStart.getTime()) / MS_PER_DAY);
     const diffDays = Math.round((endStart.getTime() - todayStart.getTime()) / MS_PER_DAY);
 
 
-    if (diffDays < 0) return null;   // 已过期:不显示剩余时间
+    if (diffDays < 0) return 0;   // 已过期:不显示剩余时间
     return diffDays + 1;             // 18号到22号:22-18=4,加1后=5天
     return diffDays + 1;             // 18号到22号:22-18=4,加1后=5天
 }
 }
 export function unioformDateTransform(date, param = "time"){
 export function unioformDateTransform(date, param = "time"){

+ 2 - 2
components/confirmModal.vue

@@ -3,11 +3,11 @@
 		<view class="modal_container" @click.stop>
 		<view class="modal_container" @click.stop>
 			<view class="modal_header">
 			<view class="modal_header">
 				<view class="header_left">
 				<view class="header_left">
-					<image src="/static/image/icon/icon_warn.png" class="warning_icon" mode="aspectFit"></image>
+					<image src="@/static/image/icon/icon_warn.png" class="warning_icon" mode="aspectFit"></image>
 					<text class="header_title">{{ title }}</text>
 					<text class="header_title">{{ title }}</text>
 				</view>
 				</view>
 				<view class="close_btn" @click="handleClose">
 				<view class="close_btn" @click="handleClose">
-					<image src="/static/image/icon/close.png" class="close_icon" mode="aspectFit"></image>
+					<image src="@/static/image/icon/close.png" class="close_icon" mode="aspectFit"></image>
 				</view>
 				</view>
 			</view>
 			</view>
 			<view class="modal_content">
 			<view class="modal_content">

+ 15 - 12
components/navBar.vue

@@ -22,7 +22,7 @@
 		<!-- 条件选择器 -->
 		<!-- 条件选择器 -->
 		<view class="filter_picker" v-if="showFilterPicker">
 		<view class="filter_picker" v-if="showFilterPicker">
 			<template v-for="(item,index) in filterPickerData" :key="index">
 			<template v-for="(item,index) in filterPickerData" :key="index">
-				<picker mode="selector" v-if="item?.list?.length > 0" :range="item.list" :value="item.valueIndex" range-key="label" style="width: calc((100% - 32rpx * 2) / 3);" @change="(e)=>ChangeFilterPicker(e,index)">
+				<picker class="item_filter_picker" mode="selector" v-if="item?.list?.length > 0" :range="item.list" :value="item.valueIndex" range-key="label" style="width: calc((100% - 32rpx * 2) / 3);" @change="(e)=>ChangeFilterPicker(e,index)">
 					<view class="filter_item">
 					<view class="filter_item">
 						<text class="filter_text">{{ item?.list?.[item.valueIndex]?.label || '' }}</text>
 						<text class="filter_text">{{ item?.list?.[item.valueIndex]?.label || '' }}</text>
 						<uni-icons type="down" size="16" color="#999999"></uni-icons>
 						<uni-icons type="down" size="16" color="#999999"></uni-icons>
@@ -32,15 +32,18 @@
 		</view>
 		</view>
 		<slot name="tabs_top_content" />
 		<slot name="tabs_top_content" />
 		<!-- tabs -->
 		<!-- tabs -->
-		<scroll-view v-if="showTabs && tabList.length > 0" class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
-			<view :class="['tab_item',{'selected':item.value==state.tabsSelected}]" v-for="item in tabList" :key="item.value" @click="SelectTabsValue(item.value)">
-				{{item.label}}
-			</view>
-		</scroll-view>
+		<view class="scroll_tabs" v-if="showTabs && tabList.length > 0">
+			<scroll-view class="scroll_tabs_view" scroll-x="true" scroll-left="0" :show-scrollbar="false">
+				<view :class="['tab_item',{'selected':item.value===state.tabsSelected}]" v-for="item in tabList" :key="item.value" @click="SelectTabsValue(item.value)">
+					{{item.label}}
+				</view>
+			</scroll-view>
+			<slot name="tabs_right_content" />
+		</view>
 		<!-- tabs 按钮 -->
 		<!-- tabs 按钮 -->
 		<scroll-view v-if="showTabBtns && tabBtns.length > 0" class="scroll_tab_btn" scroll-x="true" scroll-left="0" :show-scrollbar="false">
 		<scroll-view v-if="showTabBtns && tabBtns.length > 0" class="scroll_tab_btn" scroll-x="true" scroll-left="0" :show-scrollbar="false">
 			<slot name="tab_btns_lef" />	
 			<slot name="tab_btns_lef" />	
-			<view :class="['tab_item',{'selected':item.value==state.tabBtnSelected}]" v-for="item in tabBtns" :key="item.value" @click="SelectTabBtnsValue(item.value)">
+			<view :class="['tab_item',{'selected':item.value===state.tabBtnSelected}]" v-for="item in tabBtns" :key="item.value" @click="SelectTabBtnsValue(item.value)">
 				{{item.label}}
 				{{item.label}}
 			</view>
 			</view>
 		</scroll-view>
 		</scroll-view>
@@ -136,21 +139,21 @@
 		},//条件选择器选中的值
 		},//条件选择器选中的值
 		tabsSelected: '', //tabs 默认选中
 		tabsSelected: '', //tabs 默认选中
 		tabBtnSelected: '',//tabBtns 默认选中
 		tabBtnSelected: '',//tabBtns 默认选中
-		searchInputStyles: { //搜框样式
+		searchInputStyles: { //搜框样式
 			borderColor: '#DCDFE6',
 			borderColor: '#DCDFE6',
 			color: '#333333'
 			color: '#333333'
 		},
 		},
-		searchInputPlaceholderStyle: 'color: #C0C4CC;fontSize: 28rpx' //搜框样式
+		searchInputPlaceholderStyle: 'color: #C0C4CC;fontSize: 28rpx' //搜框样式
 	})
 	})
 	watch(()=>props.tabList,(newVal, oldVal)=>{
 	watch(()=>props.tabList,(newVal, oldVal)=>{
 		if(newVal){
 		if(newVal){
-			const firstValue = props?.tabList?.[0]?.value || '';
+			const firstValue = props?.tabList?.[0]?.value ?? '';
 			state.tabsSelected = props.defaultTabValue!==''?props.defaultTabValue : firstValue; //tab 默认值
 			state.tabsSelected = props.defaultTabValue!==''?props.defaultTabValue : firstValue; //tab 默认值
 		}
 		}
 	})
 	})
 	watch(()=>props.tabBtns,(newVal, oldVal)=>{
 	watch(()=>props.tabBtns,(newVal, oldVal)=>{
 		if(newVal){
 		if(newVal){
-			state.tabBtnSelected = props?.tabBtns?.[0]?.value || ''; //tab 默认值
+			state.tabBtnSelected = props?.tabBtns?.[0]?.value ?? ''; //tab 默认值
 		}
 		}
 	})
 	})
 	//关键字搜索
 	//关键字搜索
@@ -207,7 +210,7 @@
 		}
 		}
 	}
 	}
 	onMounted(() => {
 	onMounted(() => {
-		const firstValue = props?.tabList?.[0]?.value || '';
+		const firstValue = props?.tabList?.[0]?.value ?? '';
 		state.tabsSelected = props.defaultTabValue!==''?props.defaultTabValue : firstValue; //tab 默认值
 		state.tabsSelected = props.defaultTabValue!==''?props.defaultTabValue : firstValue; //tab 默认值
 		state.tabBtnSelected = props?.tabBtns?.[0]?.value || ''; //tabBtns 默认值
 		state.tabBtnSelected = props?.tabBtns?.[0]?.value || ''; //tabBtns 默认值
 		state.filterOpts.filterPickerValue = props.filterPickerData.map(item => item?.defaultValue ?? '');
 		state.filterOpts.filterPickerValue = props.filterPickerData.map(item => item?.defaultValue ?? '');

+ 2 - 2
components/noticeHeader.vue

@@ -7,7 +7,7 @@
 				<text class="header_title">{{ title }}</text>
 				<text class="header_title">{{ title }}</text>
 			</view>
 			</view>
 			<view v-if="showSearch" class="search_box">
 			<view v-if="showSearch" class="search_box">
-				<image src="/static/image/overview/search.png" class="search_icon" ></image>	
+				<image src="@/static/image/overview/search.png" class="search_icon" ></image>	
 				<input type="text" class="search_input" placeholder="请输入关键字搜索" placeholder-class="search_placeholder" v-model="searchWord" @input="handleSearchInput" />
 				<input type="text" class="search_input" placeholder="请输入关键字搜索" placeholder-class="search_placeholder" v-model="searchWord" @input="handleSearchInput" />
 			</view>
 			</view>
 			<text v-else-if="showSave" class="save_btn" @click="handleSave">保存</text>
 			<text v-else-if="showSave" class="save_btn" @click="handleSave">保存</text>
@@ -85,7 +85,7 @@
 				@click="handleTabChange(idx)"
 				@click="handleTabChange(idx)"
 			>{{ tab }}</text>
 			>{{ tab }}</text>
 			<view v-if="showCreateBtn && mode === 'taskOverview'" class="create_btn" @click="handleCreate">
 			<view v-if="showCreateBtn && mode === 'taskOverview'" class="create_btn" @click="handleCreate">
-				<image src="/static/image/workspace/add.png" class="add_icon" mode="aspectFit"></image>
+				<image src="@/static/image/workspace/add.png" class="add_icon" mode="aspectFit"></image>
 				<text class="create_text">新建</text>
 				<text class="create_text">新建</text>
 			</view>
 			</view>
 		</view>
 		</view>

+ 2 - 2
components/popupDialog.vue

@@ -1,10 +1,10 @@
-<template>
+<template>
 	<!-- 提示框 可自定义内容-->
 	<!-- 提示框 可自定义内容-->
 	<uni-popup ref="popupDialog" type="dialog">
 	<uni-popup ref="popupDialog" type="dialog">
 		<uni-popup-dialog :class="{'white':!showTitle,'footBorder':showFootBorder}" :showClose="showCloseBtn" :style="{'width': `${dialogWidth}rpx`}" @confirm="DialogConfirm" @close="CloseDialog">
 		<uni-popup-dialog :class="{'white':!showTitle,'footBorder':showFootBorder}" :showClose="showCloseBtn" :style="{'width': `${dialogWidth}rpx`}" @confirm="DialogConfirm" @close="CloseDialog">
 			<view class="dialog_title" v-if="showTitle">
 			<view class="dialog_title" v-if="showTitle">
 				<view class="dialog_title_lt">
 				<view class="dialog_title_lt">
-					<image v-if="popType=='alert'" src="@/static/image/icon/icon_warn.png" style="width: 40rpx;height: 40rpx;margin-left: 16rpx;"></image>
+					<image v-if="popType=='alert'" src="@/static/image/icon/icon_warn.png" style="width: 40rpx;height: 40rpx;margin-right: 16rpx;"></image>
 					<text class="title">{{title}}</text>
 					<text class="title">{{title}}</text>
 				</view>
 				</view>
 				<image v-if="showDialogClose" src="@/static/image/icon/close.png" style="width: 48rpx;height: 48rpx;" @click="CloseDialog"></image>
 				<image v-if="showDialogClose" src="@/static/image/icon/close.png" style="width: 48rpx;height: 48rpx;" @click="CloseDialog"></image>

+ 1 - 1
components/searchBar.vue

@@ -2,7 +2,7 @@
 	<!-- 搜索栏 -->
 	<!-- 搜索栏 -->
 	<view class="search_container" :style="containerStyle">
 	<view class="search_container" :style="containerStyle">
 			<view class="search_box">
 			<view class="search_box">
-				<image src="/static/image/icon/search.png" class="search_icon" mode="aspectFit"></image>
+				<image src="@/static/image/icon/search.png" class="search_icon" mode="aspectFit"></image>
 				<input type="text" class="search_input" :value="modelValue" @input="handleInput"
 				<input type="text" class="search_input" :value="modelValue" @input="handleInput"
 					placeholder="请输入关键字搜索" />
 					placeholder="请输入关键字搜索" />
 			</view>
 			</view>

+ 2 - 2
components/treeNode.vue

@@ -5,7 +5,7 @@
 				<view class="checkbox_wrap" @click.stop="handleSelect(item)">
 				<view class="checkbox_wrap" @click.stop="handleSelect(item)">
 					<view class="checkbox" :class="{ checked: item.checked, 'half-checked': item.halfChecked }">
 					<view class="checkbox" :class="{ checked: item.checked, 'half-checked': item.halfChecked }">
 						<view v-if="(item.checked || item.halfChecked) && item.children && item.children.length > 0" class="checkbox_minus"></view>
 						<view v-if="(item.checked || item.halfChecked) && item.children && item.children.length > 0" class="checkbox_minus"></view>
-						<image v-else-if="item.checked && (!item.children || item.children.length === 0)" src="/static/image/publish/correct.png" class="checkbox_check_image" mode="aspectFit"></image>
+						<image v-else-if="item.checked && (!item.children || item.children.length === 0)" src="@/static/image/publish/correct.png" class="checkbox_check_image" mode="aspectFit"></image>
 					</view>
 					</view>
 				</view>
 				</view>
 				<view class="row_text_container">
 				<view class="row_text_container">
@@ -13,7 +13,7 @@
 					<text v-if="item.userAccount" class="row_account">({{ item.userAccount }})</text>
 					<text v-if="item.userAccount" class="row_account">({{ item.userAccount }})</text>
 				</view>
 				</view>
 				<view v-if="item.children && item.children.length > 0" class="expand_icon">
 				<view v-if="item.children && item.children.length > 0" class="expand_icon">
-					<image src="/static/image/icon/xiala.png" class="expand-arrow" :class="{ expanded: expandedIds.includes(item.id) }" mode="aspectFit"></image>
+					<image src="@/static/image/icon/xiala.png" class="expand-arrow" :class="{ expanded: expandedIds.includes(item.id) }" mode="aspectFit"></image>
 				</view>
 				</view>
 			</view>
 			</view>
 
 

+ 2 - 2
components/treeNodeNoDedup.vue

@@ -5,7 +5,7 @@
 				<view class="checkbox_wrap" @click.stop="handleSelect(item)">
 				<view class="checkbox_wrap" @click.stop="handleSelect(item)">
 					<view class="checkbox" :class="{ checked: item.checked, 'half-checked': item.halfChecked }">
 					<view class="checkbox" :class="{ checked: item.checked, 'half-checked': item.halfChecked }">
 						<view v-if="(item.checked || item.halfChecked) && item.children && item.children.length > 0" class="checkbox_minus"></view>
 						<view v-if="(item.checked || item.halfChecked) && item.children && item.children.length > 0" class="checkbox_minus"></view>
-						<image v-else-if="item.checked && (!item.children || item.children.length === 0)" src="/static/image/publish/correct.png" class="checkbox_check_image" mode="aspectFit"></image>
+						<image v-else-if="item.checked && (!item.children || item.children.length === 0)" src="@/static/image/publish/correct.png" class="checkbox_check_image" mode="aspectFit"></image>
 					</view>
 					</view>
 				</view>
 				</view>
 				<view class="row_text_container">
 				<view class="row_text_container">
@@ -13,7 +13,7 @@
 					<text v-if="item.userAccount" class="row_account">({{ item.userAccount }})</text>
 					<text v-if="item.userAccount" class="row_account">({{ item.userAccount }})</text>
 				</view>
 				</view>
 				<view v-if="item.children && item.children.length > 0" class="expand_icon">
 				<view v-if="item.children && item.children.length > 0" class="expand_icon">
-					<image src="/static/image/icon/xiala.png" class="expand-arrow" :class="{ expanded: expandedIds.includes(item.id) }" mode="aspectFit"></image>
+					<image src="@/static/image/icon/xiala.png" class="expand-arrow" :class="{ expanded: expandedIds.includes(item.id) }" mode="aspectFit"></image>
 				</view>
 				</view>
 			</view>
 			</view>
 
 

+ 11 - 4
pages.json

@@ -226,16 +226,23 @@
 			}
 			}
 		},
 		},
 		{
 		{
-			"path": "pages/materialCollection/taskOverview/index",
+			"path": "pages/materialCollection/index",
 			"style": {
 			"style": {
-				"navigationBarTitleText": "任务总览",
+				"navigationBarTitleText": "材料采集",
 				"navigationStyle": "custom"
 				"navigationStyle": "custom"
 			}
 			}
 		},
 		},
 		{
 		{
-			"path": "pages/materialCollection/taskOverview/components/index",
+			"path": "pages/materialCollection/taskOverview/addEdit",
 			"style": {
 			"style": {
-				"navigationBarTitleText": "新建任务",
+				"navigationBarTitleText": "材料采集-任务总览-新建/编辑任务",
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/materialCollection/taskOverview/taskDetail",
+			"style": {
+				"navigationBarTitleText": "材料采集-任务总览-查看任务",
 				"navigationStyle": "custom"
 				"navigationStyle": "custom"
 			}
 			}
 		},
 		},

+ 5 - 4
pages/login/agreement.vue

@@ -1,4 +1,4 @@
-<template>
+<template>
 	<view class="page_body">
 	<view class="page_body">
 		<!-- 导航 -->
 		<!-- 导航 -->
 		<nav-bar height="88" backPath="" :showHeaderborder="false" title="用户协议和隐私政策" @GoBack="GoBack"></nav-bar>
 		<nav-bar height="88" backPath="" :showHeaderborder="false" title="用户协议和隐私政策" @GoBack="GoBack"></nav-bar>
@@ -55,9 +55,10 @@
 	import navBar from '@/components/navBar.vue';
 	import navBar from '@/components/navBar.vue';
 	//返回
 	//返回
 	const GoBack = () => {
 	const GoBack = () => {
-		uni.navigateTo({
-			url: '/pages/login/index'
-		});
+		uni.navigateBack();
+		// uni.navigateTo({
+		// 	url: '/pages/login/index'
+		// });
 	}
 	}
 </script>
 </script>
 
 

+ 44 - 6
pages/login/index.vue

@@ -27,7 +27,7 @@
 				<view class="text">
 				<view class="text">
 					<text class="color_999">我已阅读并同意</text>
 					<text class="color_999">我已阅读并同意</text>
 					<text class="color_blue" @click="AgreementDetails">用户协议</text>
 					<text class="color_blue" @click="AgreementDetails">用户协议</text>
-					<text class="color_blue" @click="AgreementDetails">和</text>
+					<text class="color_999">和</text>
 					<text class="color_blue" @click="AgreementDetails">隐私改策</text>
 					<text class="color_blue" @click="AgreementDetails">隐私改策</text>
 				</view>
 				</view>
 			</view>
 			</view>
@@ -47,6 +47,15 @@
 			</view>
 			</view>
 		</view>
 		</view>
 	</popupDialog>
 	</popupDialog>
+	<!-- 同意协议并登录 -->
+	<popupDialog class="agreement_dialog" ref="agreementPopupDialog" popType="custom" title="用户协议及隐私改策" :showDialogClose="false" :dialogWidth="550" @DialogConfirm="DialogAgreementConfirm">
+		<view class="agreement_popup_content">
+			<text class="color_999">我已阅读并同意</text>
+			<text class="color_blue" @click="AgreementDetails">用户协议</text>
+			<text class="color_999">和</text>
+			<text class="color_blue" @click="AgreementDetails">隐私改策</text>
+		</view>
+	</popupDialog>
 	<custom-dialog ref="popupSlideCode" title="滑动验证">
 	<custom-dialog ref="popupSlideCode" title="滑动验证">
 		<view class="slide_code_content">
 		<view class="slide_code_content">
 			<slide-code ref="slideRef" :sliderBgUrl="state.sliderBgUrl" :sliderUUID="state.sliderUUID"
 			<slide-code ref="slideRef" :sliderBgUrl="state.sliderBgUrl" :sliderUUID="state.sliderUUID"
@@ -86,6 +95,7 @@ const store = useStore();
 const route = useRoute() // 获取当前路由信息
 const route = useRoute() // 获取当前路由信息
 const popupDialogRef = ref(null);
 const popupDialogRef = ref(null);
 const popupSlideCode = ref(null);
 const popupSlideCode = ref(null);
+const agreementPopupDialog = ref(null);
 const isCheck = ref(false);
 const isCheck = ref(false);
 const state = reactive({
 const state = reactive({
 	username: '',
 	username: '',
@@ -376,11 +386,12 @@ const handleLogin = () => {
 		return;
 		return;
 	}
 	}
 	if (!isCheck.value) {
 	if (!isCheck.value) {
-		uni.showToast({
-			title: '请先阅读并同意相关协议',
-			icon: 'none', // 可选值:'success', 'loading', 'none'
-			duration: 2000 // 提示持续时间,单位毫秒
-		});
+		agreementPopupDialog.value.OpenDialog();
+		// uni.showToast({
+		// 	title: '请先阅读并同意相关协议',
+		// 	icon: 'none', // 可选值:'success', 'loading', 'none'
+		// 	duration: 2000 // 提示持续时间,单位毫秒
+		// });
 		return;
 		return;
 	}
 	}
 	user.login(params).then(res => {
 	user.login(params).then(res => {
@@ -456,6 +467,10 @@ const LoginSuccess = () => {
 		url: '/pages/workspace/index'
 		url: '/pages/workspace/index'
 	});
 	});
 }
 }
+const DialogAgreementConfirm = () => {
+	isCheck.value = true;
+	handleLogin();
+}
 const AgreementDetails = () => {
 const AgreementDetails = () => {
 	uni.navigateTo({
 	uni.navigateTo({
 		url: '/pages/login/agreement'
 		url: '/pages/login/agreement'
@@ -558,4 +573,27 @@ const AgreementDetails = () => {
 	margin-top: 20rpx;
 	margin-top: 20rpx;
 
 
 }
 }
+:deep(.agreement_dialog){
+	.dialog_title{
+		background-color: #FFFFFF;
+		justify-content: center;
+	}
+	.dialog_content{
+		min-height: auto;
+	}
+	.agreement_popup_content{
+		font-size: 24rpx;
+		display: flex;
+		width: 100%;
+		justify-content: center;
+		gap: 6rpx;
+		.color_999 {
+			color: #999999;
+			margin: 0 4rpx;
+		}
+		.color_blue {
+			color: #2e64fa;
+		}
+	}
+}
 </style>
 </style>

+ 73 - 0
pages/materialCollection/index.vue

@@ -0,0 +1,73 @@
+<template>
+	<view class="page_body">
+		<!-- 任务总览 -->
+		<task-overview v-if="state.tabBarValue=='task'"></task-overview>
+		<!-- 提交材料 -->
+		<submit-material v-if="state.tabBarValue=='target'"></submit-material>
+		<!-- 审核材料 -->
+		<review-material v-if="state.tabBarValue=='review'"></review-material>
+		<!-- 底部tabbar -->
+		<pageTabbar :tabBarValue="state.tabBarValue" :tabBarList="state.tabBarList" @ChangeTabBarValue="ChangeTabBarValue"></pageTabbar>
+	</view>
+</template>
+
+<script setup>
+	import pageTabbar from '@/components/pageTabbar.vue';//底部tabbar
+	import taskOverview from './taskOverview/index.vue';//任务总览
+	import submitMaterial from './submitMaterial/index.vue';//提交材料
+	import reviewMaterial from './reviewMaterial/index.vue';//审核材料
+	import { queryTaskMenu } from '@/reqApi/notification.js';
+	import { reactive, onMounted } from 'vue';
+	import { useStore } from 'vuex';
+	const store = useStore();
+	const state = reactive({
+		tabBarValue:'task',
+		tabBarList:[]
+	})
+	//切换tabBar
+	const ChangeTabBarValue = (name) => {
+		state.tabBarValue = name;
+	}
+	onMounted(()=>{
+		GetTaskMenu();
+	})
+	const GetTaskMenu = () => {
+		queryTaskMenu().then(res=>{
+			if(res.code == 200){
+				const menuList = res?.data || [];
+				if(menuList.indexOf('task') > -1){
+					state.tabBarList.push({
+						"pathName":"task",
+						"iconPath": "/static/image/overview/zonglan.png",
+						"selectedIconPath": "/static/image/overview/zonglanIcon.png",
+						"text": "任务总览"
+					})
+				}
+				if(menuList.indexOf('target') > -1){
+					state.tabBarList.push({
+						"pathName":"target",
+						"iconPath": "/static/image/materialCollection/tijiao.png",
+						"selectedIconPath": "/static/image/materialCollection/tijiaoIcon.png",
+						"text": "提交材料"
+					})
+				}
+				if(menuList.indexOf('review') > -1){
+					state.tabBarList.push({
+						"pathName":"review",
+						"iconPath": "/static/image/materialCollection/shenhe.png",
+						"selectedIconPath": "/static/image/materialCollection/shenheIcon.png",
+						"text": "审核材料"
+					})
+				}
+				state.tabBarValue = state.tabBarList?.[0]?.pathName || '';
+			}
+		})
+	}
+</script>
+
+<style lang="scss" scoped>
+	.page_body{
+		height: 100%;
+		min-height: auto;
+	}
+</style>

+ 321 - 227
pages/materialCollection/reviewMaterial/index.vue

@@ -1,35 +1,34 @@
 <template>
 <template>
-	<view class="page_notice" :style="{paddingTop: statusBarHeight + 430 + 'rpx', paddingBottom: safeAreaBottom + 160 + 'rpx' }">
-		<noticeHeader 
-			title="审核材料" 
-			mode="material"
-			tabMode="index"
-			:showSearch="true" 
-			:showFilter="true" 
-			:showStageBtn="true"
-			:showTabs="true" 
-			:showCreateBtn="true"
-			:tabs="tabs"
-			:activeTab="activeTab"
-			:academicYearOptions="academicYearOptions"
-			:academicYearIds="academicYearIds"
-			:categoryData="categoryData"
-			@tabChange="handleTabChange" 
-			@academicYearChange="handleAcademicYearChange"
-			@categoryChange="handleCategoryChange"
-			@materialTypeChange="handleMaterialTypeChange"
-			@searchChange="handleSearchChange"
-			@stageChange="handleStageChange"
-			@create="handleCreate">
-		</noticeHeader>
-
-		<view class="notice_content">
+	<!-- 头部 -->
+	<nav-bar height="400" backPath="workspace" title="材料采集" :filterPickerData="state.filterPickerData" :tabList="state.tabList" :onlyTitle="false" :showFilterPicker="true" :showTabs="true" rightWidth="0rpx" @CommonFilterData="CommonFilterData">
+		<template #tabs_top_content>
+			<view class="task_status_list">
+				<view :class="['item_status',{'active':item.value==state.params.taskStatus}]" v-for="item in state.taskStatusList" :key="item.value" @click="ChangeTaskStatus(item.value)">{{item.label}}</view>
+			</view>
+		</template>
+	</nav-bar>
+	<view class="page_content">
+		<scroll-view
+		    class="scroll_view_y"
+			:scroll-top="state.scrollTop"
+			scroll-y="true"
+			:refresher-enabled="false" 
+			:enable-back-to-top="true"
+			:show-scrollbar="false" 
+			:scroll-with-animation="true" 
+			refresher-default-style="none"
+			refresher-background="#F8F9FD" 
+			:refresher-triggered="state.isRefreshing" 
+			@scrolltolower="OnLoadMore"
+			@refresherrefresh="OnRefresh"
+			@scroll="OnScroll">
+			<view class="refresh_loading" v-if="state.isRefreshing"><uni-load-more status="loading" /></view>
 			<view class="notice_list">
 			<view class="notice_list">
-				<scroll-view scroll-y v-for="item in taskList" :key="item.id" class="notice_item">
+				<view v-for="item in state.pageList" :key="item.id" class="notice_item">
 					<!-- 任务内容 -->
 					<!-- 任务内容 -->
 					<view class="item_content">
 					<view class="item_content">
 						<view class="notice_title_row">
 						<view class="notice_title_row">
-							<image class="notice_icon" src="/static/image/materialCollection/docIcon.png" mode="aspectFit"></image>
+							<image class="notice_icon" src="@/static/image/materialCollection/docIcon.png" mode="aspectFit"></image>
 							<text class="notice_title">{{ item.taskName }}</text>
 							<text class="notice_title">{{ item.taskName }}</text>
 						</view>
 						</view>
 						<view class="notice_meta">
 						<view class="notice_meta">
@@ -38,246 +37,318 @@
 							</view>
 							</view>
 							<text class="meta_text ">{{ truncateText(item.departmentName, 5) }}</text>
 							<text class="meta_text ">{{ truncateText(item.departmentName, 5) }}</text>
 							<text class="meta_text ">{{ truncateText(item.materialCategoryName, 5) }}</text>
 							<text class="meta_text ">{{ truncateText(item.materialCategoryName, 5) }}</text>
-							<text class="meta_text">{{ truncateText(item.createdBy, 5) }}</text>
+							<text class="meta_text">{{ truncateText(item.createBy, 5) }}</text>
 						</view>
 						</view>
 					</view>
 					</view>
 					<!-- 任务底部 -->
 					<!-- 任务底部 -->
 					<view class="item_bottom">
 					<view class="item_bottom">
 						<view class="notice_stats">
 						<view class="notice_stats">
-							<view class="status_tag" :class="tabStatusClassMap[activeTab] || ''">
-								<text>{{ tabs[activeTab] }}: {{ item.taskTargetVos.length }}</text>
+							<view v-if="Number(item?.notReviewNum) > 0" class="status_tag notSubmitList">
+								<text>待审核:{{ item?.notReviewNum || 0 }}</text>
 							</view>
 							</view>
-							<text class="stats_text">剩余时间: {{remainingDays(item.endTime) }}天</text>
+							<text class="stats_text">
+								<template v-if="remainingDays(item.endTime) > 0">剩余时间:{{remainingDays(item.endTime) }}天</template>
+								<template v-else>结束时间:{{item.endTime }}</template>
+							</text>
 						</view>
 						</view>
 						<view class="notice_actions">
 						<view class="notice_actions">
-							<view class="action_btn edit" >
-								<text>查看</text>
+							<view class="action_btn edit">
+								<text>开始审核</text>
 							</view>
 							</view>
 						</view>
 						</view>
 					</view>
 					</view>
-				</scroll-view>
-
-				<noData v-if="taskList.length === 0" centered text="暂无审核材料" />
+				</view>
 			</view>
 			</view>
-		</view>
-
-		<common-tabbar></common-tabbar>
+			<view class="no_data" v-if="!state.isLoading && state.pageList.length == 0">
+				<image class="no_data_img" src="@/static/image/bg/no_data.png"></image>
+				<text class="no_data_text">暂无数据</text>
+			</view>
+			<uni-load-more v-if="state.pageList.length > 0" :status="state.loadStatus" />
+		</scroll-view>
 	</view>
 	</view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref, onMounted } from 'vue';
-import NoticeHeader from '@/components/noticeHeader.vue';
-import CommonTabbar from '@/components/commonTabbar.vue';
-import NoData from '@/components/noData.vue';
-import { useSafeArea } from '@/common/safeArea';
-import notification from '@/reqApi/notification.js';
-import {truncateText, remainingDays } from '@/common/common.js';
-
-const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
-
-const tabs = ['待提交', '审核中', '已驳回', '已提交'];
-const activeTab = ref(0);
-const stageIndex = ref(0);
-const academicYearIndex = ref(0);
-const academicYearOptions = ref(['']);
-const academicYearIds = ref(['']);
-const academicYearCodes = ref(['']);
-const currentSchoolYearId = ref('');
-const currentSchoolYearCode = ref('');
-const categoryIndex = ref(0);
-const categoryId = ref('');
-const materialTypeIndex = ref(0);
-const materialTypeId = ref('');
-const categoryData = ref([]);
-const word = ref('');
-const taskList = ref([]);
-const statusMap = {
-	0: '待开始',
-	1: '进行中',
-	2: '已结束'
-};
-
+import { reactive,ref,nextTick, onMounted } from 'vue';
+import navBar from '@/components/navBar.vue';
+import {getTaskTargetReview,getSchoolYearList,getCategoryList} from '@/reqApi/notification.js';
+import { truncateText,remainingDays } from '@/common/common.js';
+
+const state = reactive({
+	filterPickerData: [{
+		valueIndex:0,//默认值索引
+		defaultValue:'',//默认值
+		list:[]
+	},{
+		valueIndex:0,//默认值索引
+		defaultValue:'',//默认值
+		list:[]
+	},{
+		valueIndex:0,//默认值索引
+		defaultValue:'',//默认值
+		list:[]
+	}],
+	tabList: [{
+		label: '全部',
+		value: 0
+	}, {
+		label: '待审核',
+		value: 1
+	}, {
+		label: '已审核',
+		value: 2
+	}],
+	taskStatusList:[{
+		label:'进行中',
+		value:1
+	},{
+		label:'已结束',
+		value:2
+	}],
+	params:{//参数
+		schoolYearCode: '',//学年
+		schoolYearId:'',//学年id
+		departmentId:'',//归属部门
+		materialCategory:'',//材料类目
+		taskName:'',//任务名称
+		taskStatus:1,//任务状态 1-进行中 2-已结束
+		reviewType:0,//审核状态
+		pageSize: 30,
+		pageNum: 1,
+	},
+	pageLists:[],//全部数据
+	pageList:[],//列表数据
+	pages:0,
+	scrollTop:0,
+	oldScrollTop:0,
+	isRefreshing:false,//设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
+	isLoading:true,//加载中
+	noMoreData:false,//没有更多数据了
+	loadStatus:'more',//loading状态
+})
 const statusClassMap = {
 const statusClassMap = {
 	0: 'status_pending',
 	0: 'status_pending',
 	1: 'status_published',
 	1: 'status_published',
 	2: 'status_closed'
 	2: 'status_closed'
 };
 };
-
 const taskStatusMap = {
 const taskStatusMap = {
 	0: '待开始',
 	0: '待开始',
 	1: '进行中',
 	1: '进行中',
 	2: '已结束'
 	2: '已结束'
 }
 }
 const tabStatusClassMap = {
 const tabStatusClassMap = {
-	0: 'tab_not_submit',    // 待提交
-	1: 'tab_reviewing',     // 审核中
-	2: 'tab_rejected',      // 已驳回
-	3: 'tab_submitted'      // 已提交
+	'notSubmitList':'待提交',    // 待提交
+	'notReviewList':'审核中',     // 审核中
+	'reviewReasonList':'已驳回',      // 已驳回
+	'reviewList':'已提交'      // 已提交
 };
 };
-
-const fetchTaskList = async () => {
-	taskList.value = [];
-	try {
-		// stageIndex: 0-进行中(taskStatus=1), 1-已结束(taskStatus=2)
-		const taskStatusMap = { 0: 1, 1: 2 };
-		const params = {
-			schoolYearCode: currentSchoolYearCode.value || null,
-			schoolYearId: currentSchoolYearId.value || null,
-			departmentId: categoryId.value || null,
-			materialCategory: materialTypeId.value || null,
-			taskName: word.value || '',
-			taskStatus: taskStatusMap[stageIndex.value] || null,
-			pageNum: 1,
-			pageSize: 9999
-		};
-		const res = await notification.find_teacher_task_target_list(params);
-		if (res.data) {
-			// 根据当前选中的标签返回不同数组数据
-			const listMap = {
-				0: 'notSubmitList',     // 待提交
-				1: 'notReviewList',     // 审核中
-				2: 'reviewReasonList',  // 已驳回
-				3: 'reviewList'         // 已提交
-			};
-			const listKey = listMap[activeTab.value] || 'notSubmitList';
-			taskList.value = res.data[listKey] || [];
-		} else {
-			taskList.value = [];
-		}
-	} catch (error) {
-		console.error('获取任务列表失败:', error);
-		taskList.value = [];
-	}
-};
-
+// 学年学期列表
 const fetchSchoolYearList = async () => {
 const fetchSchoolYearList = async () => {
 	try {
 	try {
-		const res = await notification.getSchoolYearList();
+		const res = await getSchoolYearList();
 		if (res.data && Array.isArray(res.data)) {
 		if (res.data && Array.isArray(res.data)) {
-			const names = res.data.map(item => item.schoolYearName);
-			const ids = res.data.map(item => item.id);
-			const codes = res.data.map(item => item.schoolYearCode);
-			academicYearOptions.value = [...names];
-			academicYearIds.value = [...ids];
-			academicYearCodes.value = [...codes];
-			// 默认选中第一个学年学期
-			if (res.data.length > 0) {
-				academicYearIndex.value = 0;
-				currentSchoolYearId.value = res.data[0].id;
-				currentSchoolYearCode.value = res.data[0].schoolYearCode;
-			}
+			const resData = res.data;
+			state.filterPickerData[0].list = resData.map(item=>({
+				...item,
+				label:item.schoolYearName,
+				value:item.id
+			}))
+			const schoolYearId = state.filterPickerData?.[0]?.list?.[0]?.value || '';
+			const schoolYearCode = state.filterPickerData?.[0]?.list?.[0]?.schoolYearCode || '';
+			state.filterPickerData[0].defaultValue = schoolYearId;
+			state.params.schoolYearId = schoolYearId;//默认值学年id
+			state.params.schoolYearCode = schoolYearCode;//默认值学年code
 		}
 		}
 	} catch (error) {
 	} catch (error) {
 		console.error('获取学年学期列表失败:', error);
 		console.error('获取学年学期列表失败:', error);
 	}
 	}
 };
 };
-
+// 归属分类
 const fetchCategoryList = async () => {
 const fetchCategoryList = async () => {
 	try {
 	try {
-		const res = await notification.getCategoryList();
+		const res = await getCategoryList();
 		if (res.data && Array.isArray(res.data)) {
 		if (res.data && Array.isArray(res.data)) {
-			categoryData.value = res.data;
+			const categoryData = res.data;
+			const categoryList = categoryData.map(item=>({
+				...item,
+				label:item.categoryName,
+				value:item.id
+			}))
+			state.filterPickerData[1].list = [{label:'归属分类',value:''}].concat(...categoryList);
 		}
 		}
 	} catch (error) {
 	} catch (error) {
 		console.error('获取分类列表失败:', error);
 		console.error('获取分类列表失败:', error);
 	}
 	}
 };
 };
-
-onMounted(async () => {
-	initSafeArea();
-	await fetchSchoolYearList();
-	fetchCategoryList();
-	fetchTaskList();
-});
-
-const handleTabChange = (status) => {
-	activeTab.value = status;
-	fetchTaskList();
-};
-
-const handleStageChange = (index) => {
-	stageIndex.value = index;
-	// stageIndex: 0-进行中, 1-已结束
-	// 后续可以根据阶段筛选任务列表
-	fetchTaskList();
-};
-
-const handleAcademicYearChange = (index, id) => {
-	academicYearIndex.value = index;
-	currentSchoolYearId.value = id || '';
-	currentSchoolYearCode.value = academicYearCodes.value[index] || '';
-	fetchTaskList();
-};
-// 分类选择
-const handleCategoryChange = (index, id) => {
-	categoryIndex.value = index;
-	categoryId.value = id;
-	// 清空类目选择
-	materialTypeIndex.value = 0;
-	materialTypeId.value = null;
-	fetchTaskList();
-};
-// 类目选择
-const handleMaterialTypeChange = (index, id) => {
-	materialTypeIndex.value = index;
-	materialTypeId.value = id;
-	fetchTaskList();
-};
-
-const handleSearchChange = (keyword) => {
-	word.value = keyword;
-	fetchTaskList();
+//切换条件选择器
+const CommonFilterData = (filterOptions,type) => {
+	const {searchWord,filterOpts,tabsSelected} = filterOptions;
+	const {valueIndex, index,filterPickerValue} = filterOpts;
+	if(type == 'filterPicker'){
+		state.params.departmentId = filterPickerValue[1];//归属部门
+		state.params.materialCategory = filterPickerValue[2];//材料类目
+		state.filterPickerData[index].valueIndex = valueIndex;
+		if(index == 1){
+			state.filterPickerData[2].valueIndex = 0;
+			const parentData = state.filterPickerData[1].list;//分类归属
+			const childrenData = parentData?.[valueIndex]?.childList || [];//材料类目
+			const childrenList = childrenData.map(item=>({
+				...item,
+				label:item?.categoryName || '',
+				value:item?.id ?? ''
+			}))
+			if(childrenList.length){
+				childrenList.unshift({
+					label:'材料类目',
+					value:''
+				})
+			}
+			state.filterPickerData[2].list = childrenList;
+		}else if(index == 0){//学年
+			state.params.schoolYearId = filterPickerValue[0];//学年id
+			state.params.schoolYearCode = state.filterPickerData?.[index]?.list?.[valueIndex]?.schoolYearCode || '';//学年code
+		}
+	}else if(type == 'search'){
+		state.params.taskName = searchWord;//任务名称
+	}else{
+		state.params.reviewType = tabsSelected;//审核状态
+	}
+	OnLoadData(true);
+}
+//切换任务状态
+const ChangeTaskStatus = (val) => {
+	state.params.taskStatus = val;
+	OnLoadData(true);
+}
+/*
+*任务列表
+* initPage:初始分页 从第一开始
+*/
+const OnLoadData = (initPage) => {
+	// uni.showLoading({
+	// 	title: '加载中'
+	// });
+	state.isLoading = true;
+	state.loadStatus = 'loading';
+	if (initPage) {
+		state.params.pageNum = 1;//如果是下拉刷新、重新查询 默认加载第一页
+		state.pageLists = [];
+		state.pageList = [];
+		const params = {
+			schoolYearCode: state.params.schoolYearCode,
+			schoolYearId: state.params.schoolYearId,
+			departmentId: state.params.departmentId,
+			materialCategory: state.params.materialCategory,
+			taskName: state.params.taskName,
+			taskStatus: state.params.taskStatus,
+			reviewType:state.params.reviewType,
+			pageNum: state.params.pageNum,
+			pageSize: 999
+		};
+		getTaskTargetReview(params).then(res=>{
+			if (res.code == 200) {
+				const tableData = res?.data || [];
+				state.pageLists = tableData;//全部数据
+				const total = tableData?.length || 0;//总数
+				state.pages = Math.ceil(total / state.params.pageSize);//总页数
+				//默认加载
+				state.pageList = state.pageLists.slice(0, state.params.pageSize);
+				//没有更多了
+				state.noMoreData = state.params.pageNum == state.pages;
+				//分页+1
+				state.params.pageNum++;
+				state.isLoading = false;
+				state.isRefreshing = false;//下拉刷新未被触发
+				state.loadStatus = state.noMoreData?'no-more':'more';
+			}
+		}).finally(()=>{
+			// uni.hideLoading();
+			//返回到页面顶部
+			if(initPage){
+				GoTop();
+			}
+		});
+	}else{
+		const start = (state.params.pageNum - 1) * state.params.pageSize;
+		const end = start + state.params.pageSize;
+		const list = state.pageLists.slice(start, end);
+		state.pageList = [...state.pageList, ...list];
+		state.noMoreData = state.params.pageNum == state.pages;
+		state.params.pageNum++;
+		setTimeout(() => {
+			state.isLoading = false;
+			state.isRefreshing = false; //下拉刷新未被触发
+			state.loadStatus = state.noMoreData?'no-more':'more';
+		}, 0)
+	}
 };
 };
-
-const handleCreate = () => {
+// 自定义下拉刷新被触发	 下拉刷新
+const OnRefresh = () =>{
+	state.isRefreshing = true;//下拉刷新已经被触发
+	OnLoadData(true);
+}
+//滚动到底部/右边 触发上拉刷新
+const OnLoadMore = () => {
+	if (state.isLoading || state.noMoreData) return;
+	OnLoadData(false);
+}
+//	滚动时触发
+const OnScroll = (e) => {
+	state.oldScrollTop = e.detail.scrollTop;
+}
+//返回到顶部
+const GoTop = () => {
+	// 解决view层不同步的问题
+	state.scrollTop = state.oldScrollTop;
+	nextTick(() => {
+		state.scrollTop = 0
+	});
+}
+//编辑
+const handleEdit = (item) => {
 	uni.navigateTo({
 	uni.navigateTo({
-		url: '/pages/materialCollection/submitMaterial/index'
+		url: `/pages/materialCollection/taskOverview/components/index?id=${item.id}`
 	});
 	});
 };
 };
-
+//
 const handleDetail = (id) => {
 const handleDetail = (id) => {
 	uni.navigateTo({
 	uni.navigateTo({
 		url: `/pages/materialCollection/submitMaterial/index?id=${id}`
 		url: `/pages/materialCollection/submitMaterial/index?id=${id}`
 	});
 	});
 };
 };
+onMounted(async () => {
+	await fetchSchoolYearList();//学年学期列表
+	fetchCategoryList();//归属分类
+	OnLoadData(true);
+});
 </script>
 </script>
 
 
-<style lang="scss">
-.page_notice {
-	min-height: 100vh;
-	display: flex;
-	flex-direction: column;
-	background-color: #FFFFFF;
-	box-sizing: border-box;
-}
-
-.notice_content {
-	flex: 1;
-	display: flex;
-	flex-direction: column;
-	overflow: hidden;
-	padding-left: 0rpx;
-	padding-right: 0rpx;
+<style lang="scss" scoped>
+.page_content{
+	height: calc(100% - 536rpx);
+	.scroll_view_y{
+		height: 100%;
+		.refresh_loading{
+			padding: 10rpx 0;
+		}
+	}
 }
 }
-
 .notice_list {
 .notice_list {
-	flex: 1;
-	overflow-y: auto;
-	overflow-x: hidden;
-	padding: 0 24rpx;
+	width: 100%;
 	display: flex;
 	display: flex;
 	flex-direction: column;
 	flex-direction: column;
 }
 }
-
 .notice_item {
 .notice_item {
 	background-color: #F9FAFF;
 	background-color: #F9FAFF;
 	border-radius: 20rpx;
 	border-radius: 20rpx;
-	margin-bottom: 24rpx;
+	margin-top: 24rpx;
 	border: 2rpx solid #E4E7ED;
 	border: 2rpx solid #E4E7ED;
+	&:first-child{
+		margin-top: 16rpx;
+	}
 
 
 	.item_content {
 	.item_content {
-		padding: 24rpx;
+		padding: 24rpx 16rpx;
 
 
 		.notice_title_row {
 		.notice_title_row {
 			display: flex;
 			display: flex;
@@ -332,27 +403,17 @@ const handleDetail = (id) => {
 					color: #666666;
 					color: #666666;
 				}
 				}
 			}
 			}
-			.need_shenhe {
-				width: 48rpx;
-				height: 48rpx;
-				background: rgba(245,108,108,0.1);
-				border-radius: 8rpx 8rpx 8rpx 8rpx;
-				font-size: 24rpx;
-				color: #F56C6C;
-				text-align: center;
-				line-height: 48rpx;
-			}
 			.meta_text {
 			.meta_text {
 				font-size: 24rpx;
 				font-size: 24rpx;
 				color: #999999;
 				color: #999999;
 				line-height: 48rpx;
 				line-height: 48rpx;
 			}
 			}
 			.textLength {
 			.textLength {
-					max-width: 160rpx;
-					overflow: hidden;
-					text-overflow: ellipsis;
-					white-space: nowrap;
-				}
+				max-width: 160rpx;
+				overflow: hidden;
+				text-overflow: ellipsis;
+				white-space: nowrap;
+			}
 		}
 		}
 	}
 	}
 
 
@@ -371,10 +432,6 @@ const handleDetail = (id) => {
 			.stats_text {
 			.stats_text {
 				font-size: 24rpx;
 				font-size: 24rpx;
 				color: #999999;
 				color: #999999;
-
-				&:first-child {
-					margin-right: 32rpx;
-				}
 			}
 			}
 
 
 			.status_tag{
 			.status_tag{
@@ -385,19 +442,20 @@ const handleDetail = (id) => {
 				// line-height: 48rpx;
 				// line-height: 48rpx;
 				font-weight: 400;
 				font-weight: 400;
 				border-radius: 8rpx;
 				border-radius: 8rpx;
-				&.tab_not_submit {
+				flex-shrink: 0;
+				&.notSubmitList {
 					background: rgba(46,100,250,0.1);
 					background: rgba(46,100,250,0.1);
 					color: #2E64FA;
 					color: #2E64FA;
 				}
 				}
-				&.tab_reviewing {
+				&.notReviewList {
 					background: rgba(251,159,52,0.1);
 					background: rgba(251,159,52,0.1);
 					color: #FB9F34;
 					color: #FB9F34;
 				}
 				}
-				&.tab_rejected {
+				&.reviewReasonList {
 					background: rgba(245,108,108,0.1);
 					background: rgba(245,108,108,0.1);
 					color: #F56C6C;
 					color: #F56C6C;
 				}
 				}
-				&.tab_submitted {
+				&.reviewList {
 					background: rgba(43,198,68,0.1);
 					background: rgba(43,198,68,0.1);
 					color: #2BC644;
 					color: #2BC644;
 				}
 				}
@@ -407,6 +465,7 @@ const handleDetail = (id) => {
 		.notice_actions {
 		.notice_actions {
 			display: flex;
 			display: flex;
 			justify-content: flex-end;
 			justify-content: flex-end;
+			flex-shrink: 0;
 			gap: 16rpx;
 			gap: 16rpx;
 			.action_btn {
 			.action_btn {
 				font-size: 24rpx;
 				font-size: 24rpx;
@@ -452,9 +511,44 @@ const handleDetail = (id) => {
 			
 			
 		}
 		}
 	}
 	}
-
-	&:last-child {
-		margin-bottom: 0;
+}
+:deep(.scroll_tabs){
+	height: 72rpx;
+	align-items: center;
+	.scroll_tabs_view{
+		height: 56rpx;
+	}
+}
+:deep(.filter_picker){
+	gap: 16rpx !important;
+	.item_filter_picker{
+		width: calc((100% - 16rpx * 2) / 3) !important;
+	}
+}
+.task_status_list{
+	margin-top: 24rpx;
+	padding: 0 24rpx;
+	display: flex;
+	width: 100%;
+	gap:24rpx 30rpx;
+	box-sizing: border-box;
+	.item_status{
+		flex: 1;
+		display: inline-flex;
+		justify-content: center;
+		align-items: center;
+		height: 64rpx;
+		background-color: #FFFFFF;
+		border-radius: 8rpx;
+		border: 2rpx solid #DCDFE6;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #333333;
+		&.active{
+			background-color: rgba(46,100,250,0.1);
+			border: 2rpx solid #2E64FA;
+			color: #2E64FA;
+		}
 	}
 	}
 }
 }
 </style>
 </style>

+ 320 - 224
pages/materialCollection/submitMaterial/index.vue

@@ -1,35 +1,34 @@
 <template>
 <template>
-	<view class="page_notice" :style="{paddingTop: statusBarHeight + 430 + 'rpx', paddingBottom: safeAreaBottom + 160 + 'rpx' }">
-		<noticeHeader 
-			title="提交材料" 
-			mode="material"
-			tabMode="index"
-			:showSearch="true" 
-			:showFilter="true" 
-			:showStageBtn="true"
-			:showTabs="true" 
-			:showCreateBtn="true"
-			:tabs="tabs"
-			:activeTab="activeTab"
-			:academicYearOptions="academicYearOptions"
-			:academicYearIds="academicYearIds"
-			:categoryData="categoryData"
-			@tabChange="handleTabChange" 
-			@academicYearChange="handleAcademicYearChange"
-			@categoryChange="handleCategoryChange"
-			@materialTypeChange="handleMaterialTypeChange"
-			@searchChange="handleSearchChange"
-			@stageChange="handleStageChange"
-			@create="handleCreate">
-		</noticeHeader>
-
-		<view class="notice_content">
+	<!-- 头部 -->
+	<nav-bar height="400" backPath="workspace" title="材料采集" :filterPickerData="state.filterPickerData" :tabList="state.tabList" :onlyTitle="false" :showFilterPicker="true" :showTabs="true" rightWidth="0rpx" @CommonFilterData="CommonFilterData">
+		<template #tabs_top_content>
+			<view class="task_status_list">
+				<view :class="['item_status',{'active':item.value==state.params.taskStatus}]" v-for="item in state.taskStatusList" :key="item.value" @click="ChangeTaskStatus(item.value)">{{item.label}}</view>
+			</view>
+		</template>
+	</nav-bar>
+	<view class="page_content">
+		<scroll-view
+		    class="scroll_view_y"
+			:scroll-top="state.scrollTop"
+			scroll-y="true"
+			:refresher-enabled="false" 
+			:enable-back-to-top="true"
+			:show-scrollbar="false" 
+			:scroll-with-animation="true" 
+			refresher-default-style="none"
+			refresher-background="#F8F9FD" 
+			:refresher-triggered="state.isRefreshing" 
+			@scrolltolower="OnLoadMore"
+			@refresherrefresh="OnRefresh"
+			@scroll="OnScroll">
+			<view class="refresh_loading" v-if="state.isRefreshing"><uni-load-more status="loading" /></view>
 			<view class="notice_list">
 			<view class="notice_list">
-				<scroll-view scroll-y v-for="item in taskList" :key="item.id" class="notice_item">
+				<view v-for="item in state.pageList" :key="item.id" class="notice_item">
 					<!-- 任务内容 -->
 					<!-- 任务内容 -->
 					<view class="item_content">
 					<view class="item_content">
 						<view class="notice_title_row">
 						<view class="notice_title_row">
-							<image class="notice_icon" src="/static/image/materialCollection/docIcon.png" mode="aspectFit"></image>
+							<image class="notice_icon" src="@/static/image/materialCollection/docIcon.png" mode="aspectFit"></image>
 							<text class="notice_title">{{ item.taskName }}</text>
 							<text class="notice_title">{{ item.taskName }}</text>
 						</view>
 						</view>
 						<view class="notice_meta">
 						<view class="notice_meta">
@@ -44,10 +43,13 @@
 					<!-- 任务底部 -->
 					<!-- 任务底部 -->
 					<view class="item_bottom">
 					<view class="item_bottom">
 						<view class="notice_stats">
 						<view class="notice_stats">
-							<view class="status_tag" :class="tabStatusClassMap[activeTab] || ''">
-								<text>{{ tabs[activeTab] }}: {{ item.taskTargetVos.length }}</text>
+							<view class="status_tag" :class="state.params.auditStatus">
+								<text>{{ tabStatusClassMap[state.params.auditStatus] }}:{{ item?.taskTargetVos?.length || 0 }}</text>
 							</view>
 							</view>
-							<text class="stats_text">剩余时间: {{remainingDays(item.endTime) }}天</text>
+							<text class="stats_text">
+								<template v-if="remainingDays(item.endTime) > 0">剩余时间:{{remainingDays(item.endTime) }}天</template>
+								<template v-else>结束时间:{{item.endTime }}</template>
+							</text>
 						</view>
 						</view>
 						<view class="notice_actions">
 						<view class="notice_actions">
 							<view class="action_btn edit" >
 							<view class="action_btn edit" >
@@ -55,229 +57,300 @@
 							</view>
 							</view>
 						</view>
 						</view>
 					</view>
 					</view>
-				</scroll-view>
-
-				<noData v-if="taskList.length === 0" centered text="暂无提交材料" />
+				</view>
 			</view>
 			</view>
-		</view>
-
-		<common-tabbar></common-tabbar>
+			<view class="no_data" v-if="!state.isLoading && state.pageList.length == 0">
+				<image class="no_data_img" src="@/static/image/bg/no_data.png"></image>
+				<text class="no_data_text">暂无数据</text>
+			</view>
+			<uni-load-more v-if="state.pageList.length > 0" :status="state.loadStatus" />
+		</scroll-view>
 	</view>
 	</view>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref, onMounted } from 'vue';
-import NoticeHeader from '@/components/noticeHeader.vue';
-import CommonTabbar from '@/components/commonTabbar.vue';
-import NoData from '@/components/noData.vue';
-import { useSafeArea } from '@/common/safeArea';
-import notification from '@/reqApi/notification.js';
-import {truncateText, remainingDays } from '@/common/common.js';
-
-const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
-
-const tabs = ['待提交', '审核中', '已驳回', '已提交'];
-const activeTab = ref(0);
-const stageIndex = ref(0);
-const academicYearIndex = ref(0);
-const academicYearOptions = ref(['']);
-const academicYearIds = ref(['']);
-const academicYearCodes = ref(['']);
-const currentSchoolYearId = ref('');
-const currentSchoolYearCode = ref('');
-const categoryIndex = ref(0);
-const categoryId = ref('');
-const materialTypeIndex = ref(0);
-const materialTypeId = ref('');
-const categoryData = ref([]);
-const word = ref('');
-const taskList = ref([]);
-const statusMap = {
-	0: '待开始',
-	1: '进行中',
-	2: '已结束'
-};
-
+import { reactive,ref,nextTick, onMounted } from 'vue';
+import navBar from '@/components/navBar.vue';
+import {findTeacherTaskTargetList,getSchoolYearList,getCategoryList} from '@/reqApi/notification.js';
+import { truncateText,remainingDays } from '@/common/common.js';
+
+const state = reactive({
+	filterPickerData: [{
+		valueIndex:0,//默认值索引
+		defaultValue:'',//默认值
+		list:[]
+	},{
+		valueIndex:0,//默认值索引
+		defaultValue:'',//默认值
+		list:[]
+	},{
+		valueIndex:0,//默认值索引
+		defaultValue:'',//默认值
+		list:[]
+	}],
+	tabList: [{
+		label: '待提交',
+		value: 'notSubmitList'
+	}, {
+		label: '审核中',
+		value: 'notReviewList'
+	}, {
+		label: '已驳回',
+		value: 'reviewReasonList'
+	}, {
+		label: '已提交',
+		value: 'reviewList'
+	}],
+	taskStatusList:[{
+		label:'进行中',
+		value:1
+	},{
+		label:'已结束',
+		value:2
+	}],
+	params:{//参数
+		schoolYearCode: '',//学年
+		schoolYearId:'',//学年id
+		departmentId:'',//归属部门
+		materialCategory:'',//材料类目
+		taskName:'',//任务名称
+		taskStatus:1,//任务状态 1-进行中 2-已结束
+		auditStatus:'notSubmitList',//审核状态
+		pageSize: 30,
+		pageNum: 1,
+	},
+	pageLists:[],//全部数据
+	pageList:[],//列表数据
+	pages:0,
+	scrollTop:0,
+	oldScrollTop:0,
+	isRefreshing:false,//设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
+	isLoading:true,//加载中
+	noMoreData:false,//没有更多数据了
+	loadStatus:'more',//loading状态
+})
 const statusClassMap = {
 const statusClassMap = {
 	0: 'status_pending',
 	0: 'status_pending',
 	1: 'status_published',
 	1: 'status_published',
 	2: 'status_closed'
 	2: 'status_closed'
 };
 };
-
 const taskStatusMap = {
 const taskStatusMap = {
 	0: '待开始',
 	0: '待开始',
 	1: '进行中',
 	1: '进行中',
 	2: '已结束'
 	2: '已结束'
 }
 }
 const tabStatusClassMap = {
 const tabStatusClassMap = {
-	0: 'tab_not_submit',    // 待提交
-	1: 'tab_reviewing',     // 审核中
-	2: 'tab_rejected',      // 已驳回
-	3: 'tab_submitted'      // 已提交
+	'notSubmitList':'待提交',    // 待提交
+	'notReviewList':'审核中',     // 审核中
+	'reviewReasonList':'已驳回',      // 已驳回
+	'reviewList':'已提交'      // 已提交
 };
 };
-
-const fetchTaskList = async () => {
-	taskList.value = [];
-	try {
-		// stageIndex: 0-进行中(taskStatus=1), 1-已结束(taskStatus=2)
-		const taskStatusMap = { 0: 1, 1: 2 };
-		const params = {
-			schoolYearCode: currentSchoolYearCode.value || null,
-			schoolYearId: currentSchoolYearId.value || null,
-			departmentId: categoryId.value || null,
-			materialCategory: materialTypeId.value || null,
-			taskName: word.value || '',
-			taskStatus: taskStatusMap[stageIndex.value] || null,
-			pageNum: 1,
-			pageSize: 9999
-		};
-		const res = await notification.find_teacher_task_target_list(params);
-		if (res.data) {
-			// 根据当前选中的标签返回不同数组数据
-			const listMap = {
-				0: 'notSubmitList',     // 待提交
-				1: 'notReviewList',     // 审核中
-				2: 'reviewReasonList',  // 已驳回
-				3: 'reviewList'         // 已提交
-			};
-			const listKey = listMap[activeTab.value] || 'notSubmitList';
-			taskList.value = res.data[listKey] || [];
-		} else {
-			taskList.value = [];
-		}
-	} catch (error) {
-		console.error('获取任务列表失败:', error);
-		taskList.value = [];
-	}
-};
-
+// 学年学期列表
 const fetchSchoolYearList = async () => {
 const fetchSchoolYearList = async () => {
 	try {
 	try {
-		const res = await notification.getSchoolYearList();
+		const res = await getSchoolYearList();
 		if (res.data && Array.isArray(res.data)) {
 		if (res.data && Array.isArray(res.data)) {
-			const names = res.data.map(item => item.schoolYearName);
-			const ids = res.data.map(item => item.id);
-			const codes = res.data.map(item => item.schoolYearCode);
-			academicYearOptions.value = [...names];
-			academicYearIds.value = [...ids];
-			academicYearCodes.value = [...codes];
-			// 默认选中第一个学年学期
-			if (res.data.length > 0) {
-				academicYearIndex.value = 0;
-				currentSchoolYearId.value = res.data[0].id;
-				currentSchoolYearCode.value = res.data[0].schoolYearCode;
-			}
+			const resData = res.data;
+			state.filterPickerData[0].list = resData.map(item=>({
+				...item,
+				label:item.schoolYearName,
+				value:item.id
+			}))
+			const schoolYearId = state.filterPickerData?.[0]?.list?.[0]?.value || '';
+			const schoolYearCode = state.filterPickerData?.[0]?.list?.[0]?.schoolYearCode || '';
+			state.filterPickerData[0].defaultValue = schoolYearId;
+			state.params.schoolYearId = schoolYearId;//默认值学年id
+			state.params.schoolYearCode = schoolYearCode;//默认值学年code
 		}
 		}
 	} catch (error) {
 	} catch (error) {
 		console.error('获取学年学期列表失败:', error);
 		console.error('获取学年学期列表失败:', error);
 	}
 	}
 };
 };
-
+// 归属分类
 const fetchCategoryList = async () => {
 const fetchCategoryList = async () => {
 	try {
 	try {
-		const res = await notification.getCategoryList();
+		const res = await getCategoryList();
 		if (res.data && Array.isArray(res.data)) {
 		if (res.data && Array.isArray(res.data)) {
-			categoryData.value = res.data;
+			const categoryData = res.data;
+			const categoryList = categoryData.map(item=>({
+				...item,
+				label:item.categoryName,
+				value:item.id
+			}))
+			state.filterPickerData[1].list = [{label:'归属分类',value:''}].concat(...categoryList);
 		}
 		}
 	} catch (error) {
 	} catch (error) {
 		console.error('获取分类列表失败:', error);
 		console.error('获取分类列表失败:', error);
 	}
 	}
 };
 };
-
-onMounted(async () => {
-	initSafeArea();
-	await fetchSchoolYearList();
-	fetchCategoryList();
-	fetchTaskList();
-});
-
-const handleTabChange = (status) => {
-	activeTab.value = status;
-	fetchTaskList();
-};
-
-const handleStageChange = (index) => {
-	stageIndex.value = index;
-	// stageIndex: 0-进行中, 1-已结束
-	// 后续可以根据阶段筛选任务列表
-	fetchTaskList();
-};
-
-const handleAcademicYearChange = (index, id) => {
-	academicYearIndex.value = index;
-	currentSchoolYearId.value = id || '';
-	currentSchoolYearCode.value = academicYearCodes.value[index] || '';
-	fetchTaskList();
-};
-// 分类选择
-const handleCategoryChange = (index, id) => {
-	categoryIndex.value = index;
-	categoryId.value = id;
-	// 清空类目选择
-	materialTypeIndex.value = 0;
-	materialTypeId.value = null;
-	fetchTaskList();
-};
-// 类目选择
-const handleMaterialTypeChange = (index, id) => {
-	materialTypeIndex.value = index;
-	materialTypeId.value = id;
-	fetchTaskList();
-};
-
-const handleSearchChange = (keyword) => {
-	word.value = keyword;
-	fetchTaskList();
+//切换条件选择器
+const CommonFilterData = (filterOptions,type) => {
+	const {searchWord,filterOpts,tabsSelected} = filterOptions;
+	const {valueIndex, index,filterPickerValue} = filterOpts;
+	if(type == 'filterPicker'){
+		state.params.departmentId = filterPickerValue[1];//归属部门
+		state.params.materialCategory = filterPickerValue[2];//材料类目
+		state.filterPickerData[index].valueIndex = valueIndex;
+		if(index == 1){
+			state.filterPickerData[2].valueIndex = 0;
+			const parentData = state.filterPickerData[1].list;//分类归属
+			const childrenData = parentData?.[valueIndex]?.childList || [];//材料类目
+			const childrenList = childrenData.map(item=>({
+				...item,
+				label:item?.categoryName || '',
+				value:item?.id ?? ''
+			}))
+			if(childrenList.length){
+				childrenList.unshift({
+					label:'材料类目',
+					value:''
+				})
+			}
+			state.filterPickerData[2].list = childrenList;
+		}else if(index == 0){//学年
+			state.params.schoolYearId = filterPickerValue[0];//学年id
+			state.params.schoolYearCode = state.filterPickerData?.[index]?.list?.[valueIndex]?.schoolYearCode || '';//学年code
+		}
+	}else if(type == 'search'){
+		state.params.taskName = searchWord;//任务名称
+	}else{
+		state.params.auditStatus = tabsSelected;//审核状态
+	}
+	OnLoadData(true);
+}
+//切换任务状态
+const ChangeTaskStatus = (val) => {
+	state.params.taskStatus = val;
+	OnLoadData(true);
+}
+/*
+*任务列表
+* initPage:初始分页 从第一开始
+*/
+const OnLoadData = (initPage) => {
+	// uni.showLoading({
+	// 	title: '加载中'
+	// });
+	state.isLoading = true;
+	state.loadStatus = 'loading';
+	if (initPage) {
+		state.params.pageNum = 1;//如果是下拉刷新、重新查询 默认加载第一页
+		state.pageLists = [];
+		state.pageList = [];
+		const params = {
+			schoolYearCode: state.params.schoolYearCode,
+			schoolYearId: state.params.schoolYearId,
+			departmentId: state.params.departmentId,
+			materialCategory: state.params.materialCategory,
+			taskName: state.params.taskName,
+			taskStatus: state.params.taskStatus,
+			pageNum: state.params.pageNum,
+			pageSize: 999
+		};
+		findTeacherTaskTargetList(params).then(res=>{
+			if (res.code == 200) {
+				const tableData = res?.data?.[state.params.auditStatus] || [];
+				state.pageLists = tableData;//全部数据
+				const total = tableData?.length || 0;//总数
+				state.pages = Math.ceil(total / state.params.pageSize);//总页数
+				//默认加载
+				state.pageList = state.pageLists.slice(0, state.params.pageSize);
+				//没有更多了
+				state.noMoreData = state.params.pageNum == state.pages;
+				//分页+1
+				state.params.pageNum++;
+				state.isLoading = false;
+				state.isRefreshing = false;//下拉刷新未被触发
+				state.loadStatus = state.noMoreData?'no-more':'more';
+			}
+		}).finally(()=>{
+			// uni.hideLoading();
+			//返回到页面顶部
+			if(initPage){
+				GoTop();
+			}
+		});
+	}else{
+		const start = (state.params.pageNum - 1) * state.params.pageSize;
+		const end = start + state.params.pageSize;
+		const list = state.pageLists.slice(start, end);
+		state.pageList = [...state.pageList, ...list];
+		state.noMoreData = state.params.pageNum == state.pages;
+		state.params.pageNum++;
+		setTimeout(() => {
+			state.isLoading = false;
+			state.isRefreshing = false; //下拉刷新未被触发
+			state.loadStatus = state.noMoreData?'no-more':'more';
+		}, 0)
+	}
 };
 };
-
-const handleCreate = () => {
+// 自定义下拉刷新被触发	 下拉刷新
+const OnRefresh = () =>{
+	state.isRefreshing = true;//下拉刷新已经被触发
+	OnLoadData(true);
+}
+//滚动到底部/右边 触发上拉刷新
+const OnLoadMore = () => {
+	if (state.isLoading || state.noMoreData) return;
+	OnLoadData(false);
+}
+//	滚动时触发
+const OnScroll = (e) => {
+	state.oldScrollTop = e.detail.scrollTop;
+}
+//返回到顶部
+const GoTop = () => {
+	// 解决view层不同步的问题
+	state.scrollTop = state.oldScrollTop;
+	nextTick(() => {
+		state.scrollTop = 0
+	});
+}
+//编辑
+const handleEdit = (item) => {
 	uni.navigateTo({
 	uni.navigateTo({
-		url: '/pages/materialCollection/submitMaterial/index'
+		url: `/pages/materialCollection/taskOverview/components/index?id=${item.id}`
 	});
 	});
 };
 };
-
+//
 const handleDetail = (id) => {
 const handleDetail = (id) => {
 	uni.navigateTo({
 	uni.navigateTo({
 		url: `/pages/materialCollection/submitMaterial/index?id=${id}`
 		url: `/pages/materialCollection/submitMaterial/index?id=${id}`
 	});
 	});
 };
 };
+onMounted(async () => {
+	await fetchSchoolYearList();//学年学期列表
+	fetchCategoryList();//归属分类
+	OnLoadData(true);
+});
 </script>
 </script>
 
 
-<style lang="scss">
-.page_notice {
-	min-height: 100vh;
-	display: flex;
-	flex-direction: column;
-	background-color: #FFFFFF;
-	box-sizing: border-box;
-}
-
-.notice_content {
-	flex: 1;
-	display: flex;
-	flex-direction: column;
-	overflow: hidden;
-	padding-left: 0rpx;
-	padding-right: 0rpx;
+<style lang="scss" scoped>
+.page_content{
+	height: calc(100% - 536rpx);
+	.scroll_view_y{
+		height: 100%;
+		.refresh_loading{
+			padding: 10rpx 0;
+		}
+	}
 }
 }
-
 .notice_list {
 .notice_list {
-	flex: 1;
-	overflow-y: auto;
-	overflow-x: hidden;
-	padding: 0 24rpx;
+	width: 100%;
 	display: flex;
 	display: flex;
 	flex-direction: column;
 	flex-direction: column;
 }
 }
-
 .notice_item {
 .notice_item {
 	background-color: #F9FAFF;
 	background-color: #F9FAFF;
 	border-radius: 20rpx;
 	border-radius: 20rpx;
-	margin-bottom: 24rpx;
+	margin-top: 24rpx;
 	border: 2rpx solid #E4E7ED;
 	border: 2rpx solid #E4E7ED;
+	&:first-child{
+		margin-top: 16rpx;
+	}
 
 
 	.item_content {
 	.item_content {
-		padding: 24rpx;
+		padding: 24rpx 16rpx;
 
 
 		.notice_title_row {
 		.notice_title_row {
 			display: flex;
 			display: flex;
@@ -332,27 +405,17 @@ const handleDetail = (id) => {
 					color: #666666;
 					color: #666666;
 				}
 				}
 			}
 			}
-			.need_shenhe {
-				width: 48rpx;
-				height: 48rpx;
-				background: rgba(245,108,108,0.1);
-				border-radius: 8rpx 8rpx 8rpx 8rpx;
-				font-size: 24rpx;
-				color: #F56C6C;
-				text-align: center;
-				line-height: 48rpx;
-			}
 			.meta_text {
 			.meta_text {
 				font-size: 24rpx;
 				font-size: 24rpx;
 				color: #999999;
 				color: #999999;
 				line-height: 48rpx;
 				line-height: 48rpx;
 			}
 			}
 			.textLength {
 			.textLength {
-					max-width: 160rpx;
-					overflow: hidden;
-					text-overflow: ellipsis;
-					white-space: nowrap;
-				}
+				max-width: 160rpx;
+				overflow: hidden;
+				text-overflow: ellipsis;
+				white-space: nowrap;
+			}
 		}
 		}
 	}
 	}
 
 
@@ -371,10 +434,6 @@ const handleDetail = (id) => {
 			.stats_text {
 			.stats_text {
 				font-size: 24rpx;
 				font-size: 24rpx;
 				color: #999999;
 				color: #999999;
-
-				&:first-child {
-					margin-right: 32rpx;
-				}
 			}
 			}
 
 
 			.status_tag{
 			.status_tag{
@@ -385,19 +444,20 @@ const handleDetail = (id) => {
 				// line-height: 48rpx;
 				// line-height: 48rpx;
 				font-weight: 400;
 				font-weight: 400;
 				border-radius: 8rpx;
 				border-radius: 8rpx;
-				&.tab_not_submit {
+				flex-shrink: 0;
+				&.notSubmitList {
 					background: rgba(46,100,250,0.1);
 					background: rgba(46,100,250,0.1);
 					color: #2E64FA;
 					color: #2E64FA;
 				}
 				}
-				&.tab_reviewing {
+				&.notReviewList {
 					background: rgba(251,159,52,0.1);
 					background: rgba(251,159,52,0.1);
 					color: #FB9F34;
 					color: #FB9F34;
 				}
 				}
-				&.tab_rejected {
+				&.reviewReasonList {
 					background: rgba(245,108,108,0.1);
 					background: rgba(245,108,108,0.1);
 					color: #F56C6C;
 					color: #F56C6C;
 				}
 				}
-				&.tab_submitted {
+				&.reviewList {
 					background: rgba(43,198,68,0.1);
 					background: rgba(43,198,68,0.1);
 					color: #2BC644;
 					color: #2BC644;
 				}
 				}
@@ -408,6 +468,7 @@ const handleDetail = (id) => {
 			display: flex;
 			display: flex;
 			justify-content: flex-end;
 			justify-content: flex-end;
 			gap: 16rpx;
 			gap: 16rpx;
+			flex-shrink: 0;
 			.action_btn {
 			.action_btn {
 				font-size: 24rpx;
 				font-size: 24rpx;
 				padding: 12rpx 24rpx;
 				padding: 12rpx 24rpx;
@@ -452,9 +513,44 @@ const handleDetail = (id) => {
 			
 			
 		}
 		}
 	}
 	}
-
-	&:last-child {
-		margin-bottom: 0;
+}
+:deep(.scroll_tabs){
+	height: 72rpx;
+	align-items: center;
+	.scroll_tabs_view{
+		height: 56rpx;
+	}
+}
+:deep(.filter_picker){
+	gap: 16rpx !important;
+	.item_filter_picker{
+		width: calc((100% - 16rpx * 2) / 3) !important;
+	}
+}
+.task_status_list{
+	margin-top: 24rpx;
+	padding: 0 24rpx;
+	display: flex;
+	width: 100%;
+	gap:24rpx 30rpx;
+	box-sizing: border-box;
+	.item_status{
+		flex: 1;
+		display: inline-flex;
+		justify-content: center;
+		align-items: center;
+		height: 64rpx;
+		background-color: #FFFFFF;
+		border-radius: 8rpx;
+		border: 2rpx solid #DCDFE6;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #333333;
+		&.active{
+			background-color: rgba(46,100,250,0.1);
+			border: 2rpx solid #2E64FA;
+			color: #2E64FA;
+		}
 	}
 	}
 }
 }
 </style>
 </style>

+ 384 - 0
pages/materialCollection/taskOverview/addEdit.vue

@@ -0,0 +1,384 @@
+<template>
+	<view class="page_body">
+		<!-- 头部 -->
+		<nav-bar height="96" :title="state.title" :onlyTitle="true" :showHeaderborder="true" @GoBack="GoBack"></nav-bar>
+		<view class="page_content">
+			<uni-forms ref="valiForm" class="forms_style" :rules="rules" :model="state.formData" border
+				labelWidth="160rpx" label-align="right">
+				<uni-forms-item label="学年学期:" required name="schoolYearId">
+					<uni-data-select v-model="state.formData.schoolYearId" :clear="false" placeholder="请选择学年学期"
+						:localdata="state.schoolYearData" style="width: 320rpx;" @change="ChangSchoolYear"></uni-data-select>
+				</uni-forms-item>
+				<uni-forms-item label="归属分类:" required name="departmentId">
+					<uni-data-select v-model="state.formData.departmentId" :clear="false" placeholder="请选择归属分类"
+						:localdata="state.departmentData" style="width: 320rpx;"
+						@change="GetMaterialCategoryData"></uni-data-select>
+				</uni-forms-item>
+				<uni-forms-item label="材料类目:" required name="materialCategory">
+					<uni-data-select v-model="state.formData.materialCategory" :clear="false" placeholder="请选择材料类目"
+						:localdata="state.materialCategoryData" style="width: 320rpx;"></uni-data-select>
+				</uni-forms-item>
+				<uni-forms-item label="任务名称:" required name="taskName">
+					<uni-easyinput v-model="state.formData.taskName" :maxlength="100" placeholder="请输入任务名称" />
+				</uni-forms-item>
+				<uni-forms-item label="采集要求:" required name="collectionRequire">
+					<uni-easyinput type="textarea" v-model="state.formData.collectionRequire"
+						:style="state.easyinputStyle" placeholder="请输入采集要求"
+						placeholderStyle="font-weight: 400;font-size: 28rpx;color: #999999;"></uni-easyinput>
+				</uni-forms-item>
+				<uni-forms-item label="采集周期:" required name="taskTime">
+					<uni-datetime-picker type="daterange" :clear-icon="false" v-model="state.formData.taskTime"
+						placeholder="请选择采集周期" style="width: 480rpx;" />
+				</uni-forms-item>
+				<uni-forms-item label="审核机制:" required name="auditMechanism">
+					<uni-data-checkbox v-model="state.formData.auditMechanism" selectedColor="#2E64FA"
+						selectedTextColor="#333333" :localdata="state.radioList"></uni-data-checkbox>
+				</uni-forms-item>
+				<uni-forms-item label="审核人:" required name="taskAuditors" v-if="state.formData.auditMechanism === 1">
+					<zxz-uni-data-select v-model="state.formData.taskAuditors" collapse-tags :collapse-tags-num="1"
+						filterable multiple dataKey="teacherName" dataValue="teacherId" :clear="false"
+						:localdata="state.auditorsData"></zxz-uni-data-select>
+				</uni-forms-item>
+				<uni-forms-item label="采集对象:" required name="targetType">
+					<view class="forms_target">
+						<view class="target_left">
+							<text class="left_text">{{targetTypeObj[state.formData.targetType]}}</text>
+							<text class="left_text">已选32人</text>
+						</view>
+						<view class="target_right">
+							<text>选择采集对象</text>
+							<uni-icons class="right_icon" type="right"></uni-icons>
+						</view>
+					</view>
+				</uni-forms-item>
+			</uni-forms>
+		</view>
+		<view class="page_foot"><button class="btn_submit" type="primary" :loading="state.loading"
+				@click="honorTypeConfirm">确认</button></view>
+	</view>
+</template>
+
+<script setup>
+	import navBar from '@/components/navBar.vue';
+	import uniForms from '@/uni_modules/uni-forms/components/uni-forms/uni-forms.vue';
+	import uniFormsItem from '@/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue';
+	import uniEasyinput from '@/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue';
+	import uniDataSelect from '@/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue';
+	import uniDatetimePicker from '@/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue';
+	import zxzUniDataSelect from '@/uni_modules/zxz-uni-data-select/components/zxz-uni-data-select/zxz-uni-data-select.vue';
+	import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
+	import {
+		getSchoolYearList,
+		getCategoryList,
+		queryTeacherInfo,
+		getCollectionTaskInfo,
+		insertCollectionTask,
+		UpdateCollectionTask
+	} from '@/reqApi/notification.js';
+	import {
+		reactive,
+		ref,
+		onMounted,
+		nextTick
+	} from 'vue';
+	import {
+		onLoad
+	} from '@dcloudio/uni-app';
+	const state = reactive({
+		taskId: '', //任务id
+		title: '', //标题
+		type: '',
+		formData: {
+			schoolId:'',
+			schoolYearId: '', //学年学期
+			schoolYearCode:'',//学年学期code
+			departmentId: '', //归属分类
+			materialCategory: '', //材料类目
+			taskName: '', //任务名称
+			collectionRequire: '', //采集要求
+			taskTime: [], //采集周期
+			auditMechanism: 1, //审核机制 0-无需审核 1-需要审核	
+			taskAuditors: [], //审核人
+			targetType:1,//采集对象 1-按部门,2-按学科,3-按年级,4-按权限,5-按学生
+		},
+		schoolYearData:[],//学年学期
+		departmentData:[],//归属分类
+		materialCategoryData:[],//材料类目
+		auditorsData:[],//审核人
+		radioList:[{//审核机制
+			text:'需审核',
+			value:1
+		},{
+			text:'无审核',
+			value:0
+		}],
+		easyinputStyle: {
+			color: '#303133',
+			borderColor: '#E9E9E9'
+		},
+		loading: false
+	})
+	const targetTypeObj = {
+		1:'按部门',
+		2:'按学科',
+		3:'按年级',
+		4:'按权限',
+		5:'按学生'
+	}
+	const rules = ref({
+		schoolYearId: {rules: [{required: true,errorMessage: '请选择学年学期'}]},
+		departmentId: {rules: [{required: true,errorMessage: '请选择归属分类'}]},
+		materialCategory: {rules: [{required: true,errorMessage: '请选择材料类目'}]},
+		taskName: {rules: [{required: true,errorMessage: '请输入任务名称'}]},
+		collectionRequire: {rules: [{required: true,errorMessage: '请输入采集要求'}]},
+		taskTime: {rules: [{required: true,errorMessage: '请输入采集周期'}]},
+		auditMechanism: {rules: [{required: true,errorMessage: '请选择审核机制'}]},
+		targetType: {rules: [{required: true,errorMessage: '请选择采集对象'}]},
+	});
+	onLoad(async(option) => {
+		state.taskId = option.taskId;
+		state.title = state.taskId ? '编辑采集任务' : '新增采集任务';
+		uni.setStorageSync('isLoadCollectTaskOverview', false); //返回列表页是否重新加载列表
+		fetchSchoolYearList();//学年学期列表
+		QueryTeacherInfo();//审核人
+		await fetchCategoryList();//归属分类
+		if(state.taskId){
+			GetCollectionTaskInfo();
+		}
+	})
+	// 学年学期列表
+	const fetchSchoolYearList = async () => {
+		try {
+			const res = await getSchoolYearList();
+			if (res.data && Array.isArray(res.data)) {
+				const resData = res.data;
+				state.schoolYearData = resData.map(item=>({
+					...item,
+					text:item.schoolYearName,
+					value:item.id
+				}))
+				const schoolYearId = state.schoolYearData?.[0]?.value || '';
+				const schoolYearCode = state.schoolYearData?.[0]?.schoolYearCode || '';
+				state.formData.schoolYearId = schoolYearId;//默认值学年id
+				state.formData.schoolYearCode = schoolYearCode;//默认值学年code
+			}
+		} catch (error) {
+			console.error('获取学年学期列表失败:', error);
+		}
+	};
+	//改变学年学期
+	const ChangSchoolYear = (val) => {
+		state.formData.schoolYearId = val;//学年id
+		state.formData.schoolYearCode = state.schoolYearData.find(item=>item.id==val)?.schoolYearCode || '';//学年code
+	}
+	// 归属分类
+	const fetchCategoryList = async () => {
+		try {
+			const res = await getCategoryList();
+			if (res.data && Array.isArray(res.data)) {
+				const categoryData = res.data;
+				state.departmentData = categoryData.map(item=>({
+					...item,
+					text:item.categoryName,
+					value:item.id
+				}))
+				const schoolId = state.departmentData?.[0]?.schoolId || '';
+				state.formData.schoolId = schoolId;
+			}
+		} catch (error) {
+			console.error('获取分类列表失败:', error);
+		}
+	};
+	//改变归属分类
+	const GetMaterialCategoryData = (val) => {
+		const materialCategoryData = state.departmentData.find(item=>val == item.id)?.childList || [];
+		state.materialCategoryData = materialCategoryData.map(item=>({
+			...item,
+			text:item.categoryName,
+			value:item.id
+		}))
+	}
+	//审核人
+	const QueryTeacherInfo = () => {
+		queryTeacherInfo('').then(res=>{
+			if(res.code == 200){
+				state.auditorsData = res?.data || [];
+			}
+		})
+	}
+	//详情
+	const GetCollectionTaskInfo = () => {
+		getCollectionTaskInfo(state.taskId).then(res=>{
+			if(res.code == 200){
+				const resData = res?.data || null;
+				state.formData.schoolId = resData?.schoolId || '';
+				state.formData.schoolYearId = resData?.schoolYearId || '';//学年学期
+				state.formData.schoolYearCode = resData?.schoolYearCode || '';//学年学期code
+				state.formData.departmentId = resData?.departmentId || '';//学年学期code
+				Object.keys(state.formData).forEach(key=>{
+					if(key == 'taskTime'){//采集周期
+						state.formData.taskTime = [resData.startTime,resData.endTime];
+					}else if(key == 'taskAuditors'){//审核人
+						const taskAuditorsList = resData?.taskAuditors || [];
+						state.formData.taskAuditors = taskAuditorsList.map(item=>item.auditorId);
+					}else{
+						state.formData[key] = resData[key];
+						if(key=='departmentId'){
+							GetMaterialCategoryData(resData.departmentId);
+						}
+					}
+				})
+			}
+		})
+	}
+	//提交
+	const honorTypeConfirm = () => {
+		let ruleList = {};
+		if(state.formData.auditMechanism == 1){//审核人
+			const taskAuditors = {
+				taskAuditors: {rules: [{required: true,errorMessage: '请选择审核人'}]}
+			}
+			ruleList = {...rules.value,...taskAuditors};
+		}else{
+			ruleList = {...rules.value}
+		}
+		for (const key in ruleList) {
+			if (state.formData?.[key] === "" || state.formData?.[key] === null || state.formData?.[key] && state.formData?.[key]?.length === 0) {
+				const errorMessage = ruleList[key].rules[0].errorMessage;
+				uni.showToast({
+					title: errorMessage,
+					icon: 'none'
+				})
+				return false
+			}
+		}
+		state.loading = true;
+		const auditorsData = state.auditorsData.filter(item=>state.formData.taskAuditors.includes(item.teacherId));
+		const taskAuditors = auditorsData.map(item=>({
+			auditorId:item.teacherId,
+			auditorName:item.teacherName
+		}))
+		let params = {
+			schoolId: state.formData.schoolId,
+			schoolYearId: state.formData.schoolYearId,
+			schoolYearCode: state.formData.schoolYearCode,
+			departmentId: state.formData.departmentId,
+			materialCategory: state.formData.materialCategory,
+			taskName: state.formData.taskName,
+			collectionRequire: state.formData.collectionRequire,
+			startTime: state.formData.taskTime[0],
+			endTime: state.formData.taskTime[1],
+			targetType: state.formData.targetType,
+			auditMechanism: state.formData.auditMechanism,//审核机制 0-无需审核 1-需要审核
+			taskAuditors: taskAuditors,//审核人
+			taskTargets: []//采集对象明细
+		}
+		if (state.taskId) {
+			params.id = state.taskId;
+			UpdateCollectionTask(params).then(res => {
+				if (res.code == 200) {
+					uni.showToast({
+						title: '编辑成功!',
+						icon: 'none'
+					})
+					uni.setStorageSync('isLoadCollectTaskOverview', true); //返回列表页是否重新加载列表
+					GoBack();
+				}
+			}).finally(() => {
+				state.loading = false;
+			})
+		} else { //新建
+			insertCollectionTask(params).then(res => {
+				if (res.code == 200) {
+					uni.showToast({
+						title: '新建成功!',
+						icon: 'none'
+					})
+					uni.setStorageSync('isLoadCollectTaskOverview', true); //返回列表页是否重新加载列表
+					GoBack();
+				}
+			}).finally(() => {
+				state.loading = false;
+			})
+		}
+	}
+	const GoBack = () => {
+		uni.navigateBack({
+			delta: 1
+		});
+	}
+</script>
+
+<style lang="scss" scoped>
+	.page_body {
+		height: 100%;
+		min-height: auto;
+		overflow: hidden;
+	}
+
+	.page_content {
+		height: calc(100% - 250rpx);
+		overflow: auto;
+	}
+
+	.forms_style {
+		:deep(.uni-forms-item) {
+			&.uni-forms-item--border {
+				border-top: 0;
+				border-bottom: 2rpx solid #F3F3F3;
+				align-items: center;
+			}
+			.forms_target{
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				.target_left{
+					flex:1;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #2E64FA;
+					.left_text{
+						flex-shrink: 0;
+						&:last-child{
+							margin-left: 8rpx;
+						}
+					}
+				}
+				.target_right{
+					flex-shrink: 0;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #2E64FA;
+					display: inline-flex;
+					align-items: center;
+					gap:8rpx;
+					.right_icon{
+						font-size: 24rpx;
+						color: #2E64FA !important;
+					}
+				}
+			}
+		}
+	}
+
+	.page_foot {
+		position: fixed;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		padding: 20rpx 24rpx;
+		background-color: #FFFFFF;
+
+		.btn_submit {
+			width: 100%;
+			height: 88rpx;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			background-color: #2E64FA !important;
+			border-radius: 20rpx;
+			color: #FFFFFF;
+			font-size: 28rpx;
+		}
+	}
+</style>

+ 6 - 6
pages/materialCollection/taskOverview/components/index.vue

@@ -185,7 +185,7 @@
 import { ref, reactive, onMounted, computed } from 'vue';
 import { ref, reactive, onMounted, computed } from 'vue';
 import { onLoad, 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 uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
-import notification from '@/reqApi/notification.js';
+import {getSchoolYearList,getCategoryList,getAuditorList,find_collection_task_target_list,save_collection_task} from '@/reqApi/notification.js';
 import CustomRadio from '@/components/customRadio.vue';
 import CustomRadio from '@/components/customRadio.vue';
 import CommonHeader from '@/components/commonHeader.vue';
 import CommonHeader from '@/components/commonHeader.vue';
 import CustomPopupDialog from '@/components/customPopupDialog.vue';
 import CustomPopupDialog from '@/components/customPopupDialog.vue';
@@ -250,7 +250,7 @@ const originalNoticeType = ref(0);
 
 
 const fetchAcademicYearList = async () => {
 const fetchAcademicYearList = async () => {
 	try {
 	try {
-		const res = await notification.getSchoolYearList();
+		const res = await getSchoolYearList();
 		if (res.data && Array.isArray(res.data)) {
 		if (res.data && Array.isArray(res.data)) {
 			const names = res.data.map(item => item.schoolYearName);
 			const names = res.data.map(item => item.schoolYearName);
 			const ids = res.data.map(item => item.id);
 			const ids = res.data.map(item => item.id);
@@ -272,7 +272,7 @@ const fetchAcademicYearList = async () => {
 
 
 const fetchCategoryList = async () => {
 const fetchCategoryList = async () => {
 	try {
 	try {
-		const res = await notification.getCategoryList();
+		const res = await getCategoryList();
 		if (res.data && Array.isArray(res.data)) {
 		if (res.data && Array.isArray(res.data)) {
 			categoryData.value = res.data;
 			categoryData.value = res.data;
 			const categoryNames = res.data.map(item => item.categoryName || item.name);
 			const categoryNames = res.data.map(item => item.categoryName || item.name);
@@ -292,7 +292,7 @@ const fetchCategoryList = async () => {
 const searchAuditors = async () => {
 const searchAuditors = async () => {
 	auditorSearchLoading.value = true;
 	auditorSearchLoading.value = true;
 	try {
 	try {
-		const res = await notification.getAuditorList(auditorSearchKey.value || '');
+		const res = await getAuditorList(auditorSearchKey.value || '');
 		if (res.data && Array.isArray(res.data)) {
 		if (res.data && Array.isArray(res.data)) {
 			auditorListFull.value = res.data.map(item => ({
 			auditorListFull.value = res.data.map(item => ({
 				teacherId: item.teacherId || item.id,
 				teacherId: item.teacherId || item.id,
@@ -377,7 +377,7 @@ onLoad(async (options) => {
 
 
 const fetchTaskDetail = async (id) => {
 const fetchTaskDetail = async (id) => {
 	try {
 	try {
-		const res = await notification.find_collection_task_target_list({ id });
+		const res = await find_collection_task_target_list({ id });
 		if (res.data) {
 		if (res.data) {
 			const data = res.data;
 			const data = res.data;
 			formData.taskName = data.taskName || '';
 			formData.taskName = data.taskName || '';
@@ -658,7 +658,7 @@ const handleSave = async () => {
 			params.userList = userList;
 			params.userList = userList;
 		}
 		}
 
 
-		const res = await notification.save_collection_task(params);
+		const res = await save_collection_task(params);
 		if (res.code === 200) {
 		if (res.code === 200) {
 			uni.showToast({ title: '保存成功', icon: 'success' });
 			uni.showToast({ title: '保存成功', icon: 'success' });
 			setTimeout(() => {
 			setTimeout(() => {

+ 319 - 184
pages/materialCollection/taskOverview/index.vue

@@ -1,32 +1,35 @@
 <template>
 <template>
-	<view class="page_notice" :style="{paddingTop: statusBarHeight + 362 + 'rpx', paddingBottom: safeAreaBottom + 160 + 'rpx' }">
-		<noticeHeader 
-			title="任务总览" 
-			mode="taskOverview"
-			:showSearch="true" 
-			:showFilter="true" 
-			:showTabs="true" 
-			:showCreateBtn="true"
-			:tabs="tabs"
-			:activeTab="activeTab"
-			:academicYearOptions="academicYearOptions"
-			:academicYearIds="academicYearIds"
-			:categoryData="categoryData"
-			@tabChange="handleTabChange" 
-			@academicYearChange="handleAcademicYearChange"
-			@categoryChange="handleCategoryChange"
-			@materialTypeChange="handleMaterialTypeChange"
-			@searchChange="handleSearchChange"
-			@create="handleCreate">
-		</noticeHeader>
-
-		<view class="notice_content">
+	<!-- 头部 -->
+	<nav-bar height="328" backPath="workspace" title="材料采集" :filterPickerData="state.filterPickerData" :tabList="state.tabList" :onlyTitle="false" :showFilterPicker="true" :showTabs="true" rightWidth="0rpx" @CommonFilterData="CommonFilterData">
+		<template #tabs_right_content>
+			<view class="add_btn" @click="handleAddEdit('add')">
+				<image class="add_icon" src="@/static/image/icon/plusempty.png"></image>
+				<text class="add_text">新建</text>
+			</view>
+		</template>
+	</nav-bar>
+	<view class="page_content">
+		<scroll-view
+		    class="scroll_view_y"
+			:scroll-top="state.scrollTop"
+			scroll-y="true"
+			:refresher-enabled="false" 
+			:enable-back-to-top="true"
+			:show-scrollbar="false" 
+			:scroll-with-animation="true" 
+			refresher-default-style="none"
+			refresher-background="#F8F9FD" 
+			:refresher-triggered="state.isRefreshing" 
+			@scrolltolower="OnLoadMore"
+			@refresherrefresh="OnRefresh"
+			@scroll="OnScroll">
+			<view class="refresh_loading" v-if="state.isRefreshing"><uni-load-more status="loading" /></view>
 			<view class="notice_list">
 			<view class="notice_list">
-				<scroll-view scroll-y v-for="item in taskList" :key="item.id" class="notice_item">
+				<view v-for="item in state.pageList" :key="item.id" class="notice_item">
 					<!-- 任务内容 -->
 					<!-- 任务内容 -->
 					<view class="item_content">
 					<view class="item_content">
 						<view class="notice_title_row">
 						<view class="notice_title_row">
-							<image class="notice_icon" src="/static/image/materialCollection/docIcon.png" mode="aspectFit"></image>
+							<image class="notice_icon" src="@/static/image/materialCollection/docIcon.png" mode="aspectFit"></image>
 							<text class="notice_title">{{ item.taskName }}</text>
 							<text class="notice_title">{{ item.taskName }}</text>
 						</view>
 						</view>
 						<view class="notice_meta">
 						<view class="notice_meta">
@@ -44,214 +47,308 @@
 					<!-- 任务底部 -->
 					<!-- 任务底部 -->
 					<view class="item_bottom">
 					<view class="item_bottom">
 						<view class="notice_stats">
 						<view class="notice_stats">
-							<text class="stats_text">开始时间: {{ item.startTime }}</text>
+							<text class="stats_text" v-if="item.taskStatus === 0">开始时间:{{ item.startTime }}</text>
+							<text class="stats_text" v-else-if="item.taskStatus === 1">剩余时间:{{ remainingDays(item.endTime) }}天</text>
+							<text class="stats_text" v-else>结束时间:{{ item.endTime }}</text>
 						</view>
 						</view>
 						<view class="notice_actions">
 						<view class="notice_actions">
-							<view class="action_btn delete" :class="{ disable: !!item.submitNum }">
+							<view class="action_btn delete" :class="{ disable: !!item.submitNum }" @click="handleDelete(item)">
 								<text>删除</text>
 								<text>删除</text>
 							</view>
 							</view>
-							<view class="action_btn edit" @click="handleEdit(item)" >
+							<view class="action_btn edit" @click="handleAddEdit('edit',item)">
 								<text>编辑</text>
 								<text>编辑</text>
 							</view>
 							</view>
-							<view class="action_btn edit" :class="{ disableLock: item.taskStatus === 0 }">
+							<view class="action_btn edit" :class="{ disableLock: item.taskStatus === 0 }" @click="handleDetail(item.taskStatus,item.id)">
 								<text>查看</text>
 								<text>查看</text>
 							</view>
 							</view>
 						</view>
 						</view>
 					</view>
 					</view>
-				</scroll-view>
-
-				<noData v-if="taskList.length === 0" centered text="暂无任务" />
+				</view>
 			</view>
 			</view>
-		</view>
-
-		<common-tabbar></common-tabbar>
+			<view class="no_data" v-if="!state.isLoading && state.pageList.length == 0">
+				<image class="no_data_img" src="@/static/image/bg/no_data.png"></image>
+				<text class="no_data_text">暂无数据</text>
+			</view>
+			<uni-load-more v-if="state.pageList.length > 0" :status="state.loadStatus" />
+		</scroll-view>
 	</view>
 	</view>
+	<!-- 删除确认框 -->
+	<popupDialog ref="popupDelDialogRef" :showFootBorder="true" :content="state.popupDelDialog.content" @DialogConfirm="DialogDelConfirm" />
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-import { ref, onMounted } from 'vue';
-import NoticeHeader from '@/components/noticeHeader.vue';
-import CommonTabbar from '@/components/commonTabbar.vue';
-import NoData from '@/components/noData.vue';
-import { useSafeArea } from '@/common/safeArea';
-import notification from '@/reqApi/notification.js';
-import { truncateText } from '@/common/common.js';
-
-const { statusBarHeight, safeAreaBottom, initSafeArea } = useSafeArea();
-
-const tabs = ['全部', '待开始', '进行中', '已结束'];
-const activeTab = ref(-1);
-const academicYearIndex = ref(0);
-const academicYearOptions = ref(['']);
-const academicYearIds = ref(['']);
-const academicYearCodes = ref(['']);
-const currentSchoolYearId = ref('');
-const currentSchoolYearCode = ref('');
-const categoryIndex = ref(0);
-const categoryId = ref('');
-const materialTypeIndex = ref(0);
-const materialTypeId = ref('');
-const categoryData = ref([]);
-const word = ref('');
-const taskList = ref([]);
-
-const statusMap = {
-	0: '待开始',
-	1: '进行中',
-	2: '已结束'
-};
-
+import { reactive,ref,nextTick, onMounted,onUnmounted } from 'vue';
+import navBar from '@/components/navBar.vue';
+import popupDialog from '@/components/popupDialog.vue';
+import {findCollectionTask,getSchoolYearList,getCategoryList,deleteCollectionTask} from '@/reqApi/notification.js';
+import { truncateText,remainingDays } from '@/common/common.js';
+import { onShow } from '@dcloudio/uni-app';
+
+const state = reactive({
+	filterPickerData: [{
+		valueIndex:0,//默认值索引
+		defaultValue:'',//默认值
+		list:[]
+	},{
+		valueIndex:0,//默认值索引
+		defaultValue:'',//默认值
+		list:[]
+	},{
+		valueIndex:0,//默认值索引
+		defaultValue:'',//默认值
+		list:[]
+	}],
+	tabList: [{//0-待开始 1-进行中 2-已结束 全部-null
+		label: '全部',
+		value: ''
+	}, {
+		label: '待开始',
+		value: 0
+	}, {
+		label: '进行中',
+		value: 1
+	}, {
+		label: '已结束',
+		value: 2
+	}],
+	params:{//参数
+		schoolYearCode: '',//学年
+		schoolYearId:'',//学年id
+		departmentId:'',//归属部门
+		materialCategory:'',//材料类目
+		taskName:'',//任务名称
+		taskStatus:null,//任务状态 0-待开始 1-进行中 2-已结束 全部-null
+		pageSize: 30,
+		pageNum: 1,
+	},
+	pageList:[],//列表数据
+	scrollTop:0,
+	oldScrollTop:0,
+	isRefreshing:false,//设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
+	isLoading:true,//加载中
+	noMoreData:false,//没有更多数据了
+	loadStatus:'more',//loading状态
+	popupDelDialog:{//删除确认框
+		content:'',
+		id:''
+	}
+})
+const popupDelDialogRef = ref(null);
 const statusClassMap = {
 const statusClassMap = {
 	0: 'status_pending',
 	0: 'status_pending',
 	1: 'status_published',
 	1: 'status_published',
 	2: 'status_closed'
 	2: 'status_closed'
 };
 };
-
 const taskStatusMap = {
 const taskStatusMap = {
 	0: '待开始',
 	0: '待开始',
 	1: '进行中',
 	1: '进行中',
 	2: '已结束'
 	2: '已结束'
 };
 };
-
-const fetchTaskList = async () => {
-	taskList.value = [];
-	try {
-		const params = {
-			schoolYearCode: currentSchoolYearCode.value || null,
-			schoolYearId: currentSchoolYearId.value || null,
-			departmentId: categoryId.value || null,
-			materialCategory: materialTypeId.value || null,
-			taskName: word.value || '',
-			taskStatus: activeTab.value === -1 ? null : activeTab.value,
-			pageNum: 1,
-			pageSize: 9999
-		};
-		const res = await notification.find_collection_task(params);
-		if (res.data && res.data.records) {
-			taskList.value = res.data.records
-		} else {
-			taskList.value = [];
-		}
-	} catch (error) {
-		console.error('获取任务列表失败:', error);
-		taskList.value = [];
-	}
-};
-
+// 学年学期列表
 const fetchSchoolYearList = async () => {
 const fetchSchoolYearList = async () => {
 	try {
 	try {
-		const res = await notification.getSchoolYearList();
+		const res = await getSchoolYearList();
 		if (res.data && Array.isArray(res.data)) {
 		if (res.data && Array.isArray(res.data)) {
-			const names = res.data.map(item => item.schoolYearName);
-			const ids = res.data.map(item => item.id);
-			const codes = res.data.map(item => item.schoolYearCode);
-			academicYearOptions.value = [...names];
-			academicYearIds.value = [...ids];
-			academicYearCodes.value = [...codes];
-			// 默认选中第一个学年学期
-			if (res.data.length > 0) {
-				academicYearIndex.value = 0;
-				currentSchoolYearId.value = res.data[0].id;
-				currentSchoolYearCode.value = res.data[0].schoolYearCode;
-			}
+			const resData = res.data;
+			state.filterPickerData[0].list = resData.map(item=>({
+				...item,
+				label:item.schoolYearName,
+				value:item.id
+			}))
+			const schoolYearId = state.filterPickerData?.[0]?.list?.[0]?.value || '';
+			const schoolYearCode = state.filterPickerData?.[0]?.list?.[0]?.schoolYearCode || '';
+			state.filterPickerData[0].defaultValue = schoolYearId;
+			state.params.schoolYearId = schoolYearId;//默认值学年id
+			state.params.schoolYearCode = schoolYearCode;//默认值学年code
 		}
 		}
 	} catch (error) {
 	} catch (error) {
 		console.error('获取学年学期列表失败:', error);
 		console.error('获取学年学期列表失败:', error);
 	}
 	}
 };
 };
-
+// 归属分类
 const fetchCategoryList = async () => {
 const fetchCategoryList = async () => {
 	try {
 	try {
-		const res = await notification.getCategoryList();
+		const res = await getCategoryList();
 		if (res.data && Array.isArray(res.data)) {
 		if (res.data && Array.isArray(res.data)) {
-			categoryData.value = res.data;
+			const categoryData = res.data;
+			const categoryList = categoryData.map(item=>({
+				...item,
+				label:item.categoryName,
+				value:item.id
+			}))
+			state.filterPickerData[1].list = [{label:'归属分类',value:''}].concat(...categoryList);
 		}
 		}
 	} catch (error) {
 	} catch (error) {
 		console.error('获取分类列表失败:', error);
 		console.error('获取分类列表失败:', error);
 	}
 	}
 };
 };
-
-onMounted(async () => {
-	initSafeArea();
-	await fetchSchoolYearList();
-	fetchCategoryList();
-	fetchTaskList();
-});
-
-const handleTabChange = (status) => {
-	activeTab.value = status;
-	fetchTaskList();
-};
-
-const handleAcademicYearChange = (index, id) => {
-	academicYearIndex.value = index;
-	currentSchoolYearId.value = id || '';
-	currentSchoolYearCode.value = academicYearCodes.value[index] || '';
-	fetchTaskList();
-};
-// 分类选择
-const handleCategoryChange = (index, id) => {
-	categoryIndex.value = index;
-	categoryId.value = id;
-	// 清空类目选择
-	materialTypeIndex.value = 0;
-	materialTypeId.value = null;
-	fetchTaskList();
-};
-// 类目选择
-const handleMaterialTypeChange = (index, id) => {
-	materialTypeIndex.value = index;
-	materialTypeId.value = id;
-	fetchTaskList();
-};
-
-const handleSearchChange = (keyword) => {
-	word.value = keyword;
-	fetchTaskList();
-};
-
-const handleCreate = () => {
-	uni.navigateTo({
-		url: '/pages/materialCollection/taskOverview/components/index'
+//切换条件选择器
+const CommonFilterData = (filterOptions,type) => {
+	const {searchWord,filterOpts,tabsSelected} = filterOptions;
+	const {valueIndex, index,filterPickerValue} = filterOpts;
+	if(type == 'filterPicker'){
+		state.params.departmentId = filterPickerValue[1];//归属部门
+		state.params.materialCategory = filterPickerValue[2];//材料类目
+		state.filterPickerData[index].valueIndex = valueIndex;
+		if(index == 1){
+			state.filterPickerData[2].valueIndex = 0;
+			const parentData = state.filterPickerData[1].list;//分类归属
+			const childrenData = parentData?.[valueIndex]?.childList || [];//材料类目
+			const childrenList = childrenData.map(item=>({
+				...item,
+				label:item?.categoryName || '',
+				value:item?.id ?? ''
+			}))
+			if(childrenList.length){
+				childrenList.unshift({
+					label:'材料类目',
+					value:''
+				})
+			}
+			state.filterPickerData[2].list = childrenList;
+		}else if(index == 0){//学年
+			state.params.schoolYearId = filterPickerValue[0];//学年id
+			state.params.schoolYearCode = state.filterPickerData?.[index]?.list?.[valueIndex]?.schoolYearCode || '';//学年code
+		}
+	}else if(type == 'search'){
+		state.params.taskName = searchWord;//任务名称
+	}else{
+		state.params.taskStatus = tabsSelected;//任务状态 0-待开始 1-进行中 2-已结束 全部-null
+	}
+	OnLoadData(true);
+}
+/*
+*任务列表
+* initPage:初始分页 从第一开始
+*/
+const OnLoadData = (initPage) => {
+	// uni.showLoading({
+	// 	title: '加载中'
+	// });
+	if (initPage) state.params.pageNum = 1;//如果是下拉刷新、重新查询 默认加载第一页
+	state.isLoading = true;
+	state.loadStatus = 'loading';
+	const params = {
+		schoolYearCode: state.params.schoolYearCode,
+		schoolYearId: state.params.schoolYearId,
+		departmentId: state.params.departmentId,
+		materialCategory: state.params.materialCategory,
+		taskName: state.params.taskName,
+		taskStatus: state.params.taskStatus,
+		pageNum: state.params.pageNum,
+		pageSize: state.params.pageSize
+	};
+	findCollectionTask(params).then(res=>{
+		if (res.code == 200) {
+			const total = Number(res?.data?.total) || 0;//总数
+			const pages = Math.ceil(total / state.params.pageSize);//总页数
+			const recordsData = res?.data?.records || []
+			state.pageList = initPage ? recordsData : [...state.pageList,...recordsData];
+			state.noMoreData = state.params.pageNum == pages;
+			state.params.pageNum++;
+		}
+	}).finally(()=>{
+		// uni.hideLoading();
+		state.isLoading = false;
+		state.isRefreshing = false;//下拉刷新未被触发
+		if(state.noMoreData){
+			state.loadStatus = 'no-more';
+		}else{
+			state.loadStatus = 'more';
+		}
+		//返回到页面顶部
+		if(initPage){
+			GoTop();
+		}
 	});
 	});
 };
 };
-
-const handleEdit = (item) => {
+// 自定义下拉刷新被触发	 下拉刷新
+const OnRefresh = () =>{
+	state.isRefreshing = true;//下拉刷新已经被触发
+	OnLoadData(true);
+}
+//滚动到底部/右边 触发上拉刷新
+const OnLoadMore = () => {
+	if (state.isLoading || state.noMoreData) return;
+	OnLoadData(false);
+}
+//	滚动时触发
+const OnScroll = (e) => {
+	state.oldScrollTop = e.detail.scrollTop;
+}
+//返回到顶部
+const GoTop = () => {
+	// 解决view层不同步的问题
+	state.scrollTop = state.oldScrollTop;
+	nextTick(() => {
+		state.scrollTop = 0
+	});
+}
+//删除弹框
+const handleDelete = (item) => {
+	if(!!item.submitNum) return false
+	state.popupDelDialog.content = `确定要删除当前任务吗?`;
+	state.popupDelDialog.id = item.id;
+	popupDelDialogRef.value.OpenDialog();
+}
+//确定删除
+const DialogDelConfirm = () => {
+	deleteCollectionTask(state.popupDelDialog.id).then(res=>{
+		if(res.code == 200){
+			uni.showToast({
+				title: '删除成功!',
+				icon: 'none'
+			});
+			OnLoadData(true);
+		}else{
+			uni.showToast({
+				title: res.msg,
+				icon: 'none'
+			});
+		}
+	})
+}
+//新建、编辑
+const handleAddEdit = (type,item) => {
 	uni.navigateTo({
 	uni.navigateTo({
-		url: `/pages/materialCollection/taskOverview/components/index?id=${item.id}`
+		url: `/pages/materialCollection/taskOverview/addEdit?taskId=${item?.id || ''}`
 	});
 	});
 };
 };
-
-const handleDetail = (id) => {
+//查看任务
+const handleDetail = (taskStatus,id) => {
+	if (taskStatus === 0) return;
 	uni.navigateTo({
 	uni.navigateTo({
-		url: `/pages/materialCollection/submitMaterial/index?id=${id}`
+		url: `/pages/materialCollection/taskOverview/taskDetail?taskId=${id}&taskStatus=${taskStatus}`
 	});
 	});
 };
 };
+onMounted(async () => {
+	await fetchSchoolYearList();//学年学期列表
+	fetchCategoryList();//归属分类
+	OnLoadData(true);
+});
+onShow(()=>{
+	const isLoadCollectTaskOverview = uni.getStorageSync('isLoadCollectTaskOverview');
+	if(isLoadCollectTaskOverview){
+		OnLoadData(true);
+	}
+})
+onUnmounted(()=>{
+	uni.setStorageSync('isLoadCollectTaskOverview', false);
+})
 </script>
 </script>
 
 
-<style lang="scss">
-.page_notice {
-	min-height: 100vh;
-	display: flex;
-	flex-direction: column;
-	background-color: #FFFFFF;
-	box-sizing: border-box;
-}
-
-.notice_content {
-	flex: 1;
-	display: flex;
-	flex-direction: column;
-	overflow: hidden;
-	padding-left: 0rpx;
-	padding-right: 0rpx;
+<style lang="scss" scoped>
+.page_content{
+	height: calc(100% - 464rpx);
+	.scroll_view_y{
+		height: 100%;
+		.refresh_loading{
+			padding: 10rpx 0;
+		}
+	}
 }
 }
-
 .notice_list {
 .notice_list {
-	flex: 1;
-	overflow-y: auto;
-	overflow-x: hidden;
-	padding: 0 24rpx;
+	width: 100%;
 	display: flex;
 	display: flex;
 	flex-direction: column;
 	flex-direction: column;
 }
 }
@@ -259,11 +356,14 @@ const handleDetail = (id) => {
 .notice_item {
 .notice_item {
 	background-color: #F9FAFF;
 	background-color: #F9FAFF;
 	border-radius: 20rpx;
 	border-radius: 20rpx;
-	margin-bottom: 24rpx;
+	margin-top: 24rpx;
 	border: 2rpx solid #E4E7ED;
 	border: 2rpx solid #E4E7ED;
+	&:first-child{
+		margin-top: 16rpx;
+	}
 
 
 	.item_content {
 	.item_content {
-		padding: 24rpx;
+		padding: 24rpx 16rpx;
 
 
 		.notice_title_row {
 		.notice_title_row {
 			display: flex;
 			display: flex;
@@ -325,8 +425,9 @@ const handleDetail = (id) => {
 				border-radius: 8rpx 8rpx 8rpx 8rpx;
 				border-radius: 8rpx 8rpx 8rpx 8rpx;
 				font-size: 24rpx;
 				font-size: 24rpx;
 				color: #F56C6C;
 				color: #F56C6C;
-				text-align: center;
-				line-height: 48rpx;
+				display: inline-flex;
+				align-items: center;
+				justify-content: center;
 			}
 			}
 			.meta_text {
 			.meta_text {
 				font-size: 24rpx;
 				font-size: 24rpx;
@@ -367,7 +468,7 @@ const handleDetail = (id) => {
 			display: flex;
 			display: flex;
 			justify-content: flex-end;
 			justify-content: flex-end;
 			gap: 16rpx;
 			gap: 16rpx;
-
+			flex-shrink: 0;
 			.action_btn {
 			.action_btn {
 				font-size: 24rpx;
 				font-size: 24rpx;
 				padding: 12rpx 24rpx;
 				padding: 12rpx 24rpx;
@@ -418,4 +519,38 @@ const handleDetail = (id) => {
 		margin-bottom: 0;
 		margin-bottom: 0;
 	}
 	}
 }
 }
+:deep(.scroll_tabs){
+	height: 72rpx;
+	align-items: center;
+	.scroll_tabs_view{
+		height: 56rpx;
+	}
+}
+:deep(.filter_picker){
+	gap: 16rpx !important;
+	.item_filter_picker{
+		width: calc((100% - 16rpx * 2) / 3) !important;
+	}
+	
+}
+.add_btn{
+	width: 148rpx;
+	height: 72rpx;
+	background-color: #2E64FA;
+	border-radius: 8rpx;
+	border: 2rpx solid #2E64FA;
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	.add_icon{
+		width: 28rpx;
+		height: 28rpx;
+		margin-right: 8rpx;
+	}
+	.add_text{
+		font-weight: 500;
+		font-size: 28rpx;
+		color: #FFFFFF;
+	}
+}
 </style>
 </style>

+ 594 - 0
pages/materialCollection/taskOverview/taskDetail.vue

@@ -0,0 +1,594 @@
+<template>
+	<view class="page_body">
+		<!-- 头部 -->
+		<nav-bar height="96" title="任务详情" :onlyTitle="true" :showHeaderborder="true" @GoBack="GoBack"></nav-bar>
+		<!-- 吸顶 -->
+		<uv-sticky style="top:98rpx">
+			<view class="search_tabs" v-if="state.isSticky">
+				<!-- 搜索框 -->
+				<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
+					:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
+					<template #left>
+						<image src="@/static/image/overview/search.png" class="search_icon"></image>
+					</template>
+				</uni-easyinput>
+				<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
+					<view :class="['tab_item',{'selected':item.value==state.tabsSelected}]" v-for="item in state.tabList"
+						:key="item.value" @click="SelectTabsValue(item.value)">
+						{{item.label}}
+					</view>
+				</scroll-view>
+			</view>
+		</uv-sticky>
+		<view class="scroll_view_box">
+			<scroll-view
+				class="scroll_view_y" 
+				:scroll-top="state.scrollTop" 
+				scroll-y="true" 
+				:refresher-enabled="false"
+				:enable-back-to-top="true" 
+				:show-scrollbar="false" 
+				:scroll-with-animation="true"
+				refresher-default-style="none" 
+				refresher-background="#F8F9FD" 
+				:refresher-triggered="state.isRefreshing"
+				@scrolltolower="OnLoadMore" 
+				@refresherrefresh="OnRefresh" 
+				@scroll="OnScroll">
+				<view class="refresh_loading" v-if="state.isRefreshing"><uni-load-more status="loading" /></view>
+				<view class="page_content padding_btm">
+					<view class="task_title">{{state?.details?.taskName}}</view>
+					<view class="task_class_collect">
+						<text class="class_item">{{state?.details?.departmentName}}</text>
+						<text class="class_item">{{state?.details?.materialCategoryName}}</text>
+						<text class="class_item">{{state?.details?.createdBy}}</text>
+					</view>
+					<view class="task_time">
+						<view class="time_day">
+							<text class="time_item">{{state?.details?.startTime}}</text>
+							<text class="time_item">至</text>
+							<text class="time_item">{{state?.details?.endTime}}</text>
+							<text class="time_item" v-if="state.taskStatus!== 2 && remainingDays(state?.details?.endTime) > 0">剩余{{remainingDays(state?.details?.endTime)}}</text>
+						</view>
+						<view :class="['task_status', statusClassMap[state.taskStatus]]">
+							{{taskStatusMap[state.taskStatus]}}
+						</view>
+					</view>
+					<view :class="['task_desc',{'over':!state.isExpand}]">
+						采集要求:{{state?.details?.collectionRequire}}
+					</view>
+					<view class="task_desc_all">
+						采集要求:{{state?.details?.collectionRequire}}
+					</view>
+					<view class="expand_btn" v-if="state.showExpandBtn" @click="toggleExpand"><text
+							class="expand_text">{{!state.isExpand?'展开':'收起'}}</text><uni-icons class="expand_icon"
+							:type="!state.isExpand?'down':'up'"></uni-icons></view>
+				</view>
+				<view class="row_gap"></view>
+				<!-- 吸顶 -->
+				<!-- <uv-sticky style="top:98rpx"> -->
+				<view class="search_tabs">
+					<!-- 搜索框 -->
+					<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
+						:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
+						<template #left>
+							<image src="@/static/image/overview/search.png" class="search_icon"></image>
+						</template>
+					</uni-easyinput>
+					<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
+						<view :class="['tab_item',{'selected':item.value==state.tabsSelected}]" v-for="item in state.tabList"
+							:key="item.value" @click="SelectTabsValue(item.value)">
+							{{item.label}}
+						</view>
+					</scroll-view>
+				</view>	
+				<!-- </uv-sticky> -->
+				<view class="page_content page_content_data">
+						<view class="total">共 {{state[`${state.tabsSelected}List`]?.length || 0}} 人</view>
+						<view class="list_item" v-for="item in state.tabListData" :Key="item.id">
+							<view class="item_name_file">
+								<view class="name_file">
+									<text class="name">刘惟安</text>
+									<text class="file_num">文件数量:2</text>
+								</view>
+								<view>查看</view>
+							</view>
+							<view class=""></view>
+						</view>
+						<view class="no_data" v-if="!state.isLoading && state.tabListData.length == 0">
+							<image class="no_data_img" src="@/static/image/bg/no_data.png"></image>
+							<text class="no_data_text">暂无数据</text>
+						</view>
+				</view>
+				<uni-load-more v-if="state.tabListData.length > 0" :status="state.loadStatus" />
+			</scroll-view>	
+		</view>
+	</view>
+</template>
+
+<script setup>
+	import uniEasyinput from '@/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue';
+	import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
+	import uvSticky from '@/uni_modules/uv-sticky/components/uv-sticky/uv-sticky.vue'; //吸顶
+	import navBar from '@/components/navBar.vue';
+	import { remainingDays } from '@/common/common.js';
+	import {
+		GetCollectionTask,
+		getTaskTargetList
+	} from '@/reqApi/notification.js';
+	import {
+		onLoad
+	} from '@dcloudio/uni-app';
+	import {
+		reactive,
+		ref,
+		nextTick,
+		getCurrentInstance,
+		onMounted
+	} from 'vue';
+	const state = reactive({
+		taskId: '', //任务id
+		taskStatus:'',//任务状态 0-未开始 1-进行中 2-结束
+		searchWord: '', //搜索关键词
+		searchInputStyles: { //搜索框样式
+			borderColor: '#DCDFE6',
+			color: '#333333'
+		},
+		searchInputPlaceholderStyle: 'color: #C0C4CC;fontSize: 28rpx', //搜索框样式
+		tabsSelected: '', //默认选中tab值
+		tabList: [], //tab列表
+		reviewTabList: [{
+			label: '待审核',
+			value: 'notReview'
+		}, {
+			label: '已审核',
+			value: 'review'
+		}, {
+			label: '已驳回',
+			value: 'reviewReason'
+		}, {
+			label: '待提交',
+			value: 'notSubmit'
+		}], //需审核
+		noReviewTabList: [{
+			label: '待提交',
+			value: 'notSubmit'
+		}, {
+			label: '已提交',
+			value: 'review'
+		}], //无需审核
+		showExpandBtn: false, //是否显示展开按钮
+		isExpand: false, //是否展开
+		pageSize: 30,
+		pageNum: 1,
+		scrollTop: 0,
+		oldScrollTop: 0,
+		isRefreshing: false, //设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发
+		isLoading: true, //加载中
+		noMoreData: false, //没有更多数据了
+		loadStatus: 'more', //loading状态
+		details: {}, //详情信息
+		notReviewList: [],//待审核
+		notSubmitList: [],//待提交
+		reviewList: [],//已审核
+		reviewReasonList: [],//已驳回
+		notReviewPagess: 0,//待审核分页
+		notSubmitPages: 0,//待提交分页
+		reviewPagess: 0,//已审核分页
+		reviewReasonPagess: 0,//已驳回分页
+		tabListData: [], //列表数据
+		searchBoxTop:0,//搜索框距离顶部的高度
+		isSticky:false,//是否吸顶
+	});
+	const statusClassMap = {
+		0: 'status_pending',
+		1: 'status_published',
+		2: 'status_closed'
+	};
+	const taskStatusMap = {
+		0: '待开始',
+		1: '进行中',
+		2: '已结束'
+	};
+	onLoad((option) => {
+		state.taskId = option.taskId;
+		state.taskStatus = option.taskStatus;
+	})
+	onMounted(() => {
+		QueryCollectionTask();//获取指定的采集任务详情
+		OnLoadData(true,true); // 数据加载完成后触发 checkTextOverflow
+	});
+	//获取指定的采集任务详情
+	const QueryCollectionTask = () => {
+		GetCollectionTask(state.taskId).then(res=>{
+			if(res.code == 200){
+				state.details = res?.data || {};
+				// 审核机制 0-无需审核 1-需要审核
+				state.tabList = state.details.auditMechanism === 1 ? state.reviewTabList:state.noReviewTabList;
+				state.tabsSelected = state.tabList?.[0]?.value || '';
+			}
+		})
+	}
+	const checkTextOverflow = () => {
+		nextTick(() => {
+			const instance = getCurrentInstance();
+			// 安全保护
+			if (!instance || !instance.proxy) {
+				// 备用方案:全局查询(要求元素 class 唯一)
+				let taskDescAllHeight = 0,
+					taskDescHeight = 0;
+				const query = uni.createSelectorQuery();
+				query.select('.task_desc_all').boundingClientRect((rect) => {
+					taskDescAllHeight = rect?.height || 0;
+				});
+				query.select('.task_desc').boundingClientRect((rect) => {
+					taskDescHeight = rect?.height || 0;
+				});
+				query.select('.page_content_data').boundingClientRect((rect) => {
+					state.searchBoxTop = rect?.top || 0;
+				});
+				query.exec(() => {
+					// 所有回调执行完毕后触发
+					state.showExpandBtn = taskDescAllHeight > taskDescHeight + 1;
+				});
+				return;
+			}
+			let taskDescAllHeight = 0,
+				taskDescHeight = 0;
+			const query = uni.createSelectorQuery().in(instance.proxy);
+			query.select('.task_desc_all').boundingClientRect((rect) => {
+				taskDescAllHeight = rect?.height || 0;
+			});
+			query.select('.task_desc').boundingClientRect((rect) => {
+				taskDescHeight = rect?.height || 0;
+			});
+			query.select('.page_content_data').boundingClientRect((rect) => {
+				state.searchBoxTop = rect?.top || 0;
+			});
+			query.exec(() => {
+				// 所有回调执行完毕后触发
+				state.showExpandBtn = taskDescAllHeight > taskDescHeight + 1;
+			});
+		});
+	}
+	// 展开收起切换
+	const toggleExpand = () => {
+		state.isExpand = !state.isExpand;
+	}
+	//切换tab
+	const SelectTabsValue = (val) => {
+		state.tabsSelected = val;
+		OnLoadData(true);
+	}
+	//搜索
+	const HandleSearchInput = (val) => {
+		state.searchWord = val;
+		OnLoadData(true);
+	}
+	const ToSafeArr = (val) => {
+	  if (Array.isArray(val)) return val
+	  return val ? [val] : []
+	}
+	/*
+	 *详情
+	 * initPage:初始分页 从第一开始
+	 * initData:初始加载
+	 */
+	const OnLoadData = (initPage,initData = false) => {
+		state.isLoading = true;
+		state.loadStatus = 'loading';
+		if (initPage) {
+			state.pageNum = 1; //如果是下拉刷新、重新查询 默认加载第一页
+			getTaskTargetList({
+				taskId: state.taskId,
+				queryStr: state.searchWord
+			}).then(res => {
+				if (res.code == 200) {
+					const data = res?.data ?? {};
+					// 列表全部数据
+					state.notSubmitList = ToSafeArr(data.notSubmitList);//待提交
+					state.notReviewList = ToSafeArr(data.notReviewList);//待审核
+					const reviewData = ToSafeArr(data.reviewList);
+					const submitData = ToSafeArr(data.submitList);
+					state.reviewList = reviewData.length ? reviewData : submitData;//已审核
+					state.reviewReasonList = ToSafeArr(data.reviewReasonList);//已驳回
+					//处理分页-----
+					const total = state[`${state.tabsSelected}List`]?.length || 0;
+					state[`${state.tabsSelected}Pages`] = Math.ceil(total / state.pageSize);//总页数
+					//默认加载
+					state.tabListData = state[`${state.tabsSelected}List`].slice(0, state.pageSize);
+					//没有更多了
+					state.noMoreData = state.pageNum == state[`${state.tabsSelected}Pages`];
+					//分页+1
+					state.pageNum++;
+					state.isLoading = false;
+					state.isRefreshing = false;//下拉刷新未被触发
+					state.loadStatus = state.noMoreData?'no-more':'more';
+					if(initData){
+						checkTextOverflow();
+					}
+				}
+			}).finally(() => {
+				//返回到页面顶部
+				if (initPage) {
+					GoTop();
+				}
+			})
+		}else{
+			const start = (state.pageNum - 1) * state.pageSize;
+			const end = start + state.pageSize;
+			const list = state[`${state.tabsSelected}List`].slice(start, end);
+			state.tabListData = [...state.tabListData, ...list];
+			state.noMoreData = state.pageNum == state[`${state.tabsSelected}Pages`];
+			state.pageNum++;
+			setTimeout(() => {
+				state.isLoading = false;
+				state.isRefreshing = false; //下拉刷新未被触发
+				state.loadStatus = state.noMoreData?'no-more':'more';
+			}, 0)
+		}
+	}
+	// 自定义下拉刷新被触发	 下拉刷新
+	const OnRefresh = () => {
+		state.isRefreshing = true; //下拉刷新已经被触发
+		OnLoadData(true);
+	}
+	//滚动到底部/右边 触发上拉刷新
+	const OnLoadMore = () => {
+		if (state.isLoading || state.noMoreData) return;
+		OnLoadData(false);
+	}
+	//	滚动时触发
+	const OnScroll = (e) => {
+		const scrollTop = e.detail.scrollTop;
+		if(scrollTop > state.searchBoxTop){
+			state.isSticky = true;
+		}else{
+			state.isSticky = false;
+		}
+		state.oldScrollTop = scrollTop;
+	}
+	//返回到顶部
+	const GoTop = () => {
+		// 解决view层不同步的问题
+		state.scrollTop = state.oldScrollTop;
+		nextTick(() => {
+			state.scrollTop = 0
+		});
+	}
+	//返回
+	const GoBack = () => {
+		uni.navigateBack({
+			delta: 1
+		});
+	}
+</script>
+
+<style scoped lang="scss">
+	.page_body{
+		height: 100%;
+		min-height: auto;
+		.scroll_view_box{
+			width: 100%;
+			display: flex;
+			flex-direction: column;
+			height: calc(100% - 96rpx);
+		}
+		.scroll_view_y {
+			height: 100%;
+		
+			.refresh_loading {
+				padding: 10rpx 0;
+			}
+		}
+	}
+	.page_content {
+		&.padding_btm {
+			padding-bottom: 24rpx;
+
+			.task_title {
+				font-weight: 500;
+				font-size: 32rpx;
+				color: #333333;
+				margin-top: 24rpx;
+			}
+
+			.task_class_collect {
+				display: inline-flex;
+				align-items: center;
+				flex-wrap: wrap;
+				width: 100%;
+				margin-top: 16rpx;
+				gap: 16rpx;
+				.class_item {
+					font-weight: 400;
+					font-size: 24rpx;
+					color: #999999;
+				}
+			}
+
+			.task_time {
+				display: flex;
+				align-items: flex-start;
+				width: 100%;
+				margin-top: 16rpx;
+
+				.time_day {
+					display: inline-flex;
+					align-items: center;
+					flex-wrap: wrap;
+					flex: 1;
+
+					.time_item {
+						font-weight: 400;
+						font-size: 24rpx;
+						line-height: 48rpx;
+						color: #999999;
+
+						&:nth-child(2) {
+							margin: 0 8rpx;
+						}
+
+						&:nth-child(4) {
+							color: #2E64FA;
+							margin-left: 16rpx;
+						}
+					}
+				}
+
+				.task_status {
+					display: inline-flex;
+					align-items: center;
+					height: 48rpx;
+					padding: 0 12rpx;
+					border-radius: 8rpx;
+					font-weight: 400;
+					font-size: 24rpx;
+
+					&.status_pending {
+						background: rgba(46, 100, 250, 0.1);
+						color: #2E64FA;
+					}
+					
+					&.status_published {
+						background: rgba(82, 196, 26, 0.1);
+						color: #2BC644;
+					}
+					
+					&.status_closed {
+						background: #6666661a;
+						color: #666666;
+					}
+				}
+			}
+
+			.task_desc {
+				margin-top: 24rpx;
+				display: flex;
+				width: 100%;
+				padding-top: 24rpx;
+				border-top: 2rpx solid #F3F3F3;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #999999;
+				line-height: 44rpx;
+				box-sizing: border-box;
+				position: relative;
+
+				&.over {
+					max-height: 168rpx;
+					overflow: hidden;
+					transition: all 0.25s;
+					display: -webkit-box;
+					-webkit-line-clamp: 3;
+					-webkit-box-orient: vertical;
+				}
+			}
+
+			.task_desc_all {
+				display: flex;
+				width: 100%;
+				padding-top: 24rpx;
+				border-top: 2rpx solid #F3F3F3;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #999999;
+				line-height: 44rpx;
+				box-sizing: border-box;
+				position: absolute;
+				left: -9999px;
+				top: 0;
+				visibility: hidden; // 不可见但占据空间(不影响布局,因为absolute)
+				pointer-events: none;
+			}
+
+			.expand_btn {
+				width: 100%;
+				height: 40rpx;
+				background-color: #FFFFFF;
+				display: flex;
+				justify-content: flex-end;
+				align-items: center;
+
+				.expand_text {
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #2E64FA;
+					margin-right: 8rpx;
+				}
+
+				.expand_icon {
+					font-size: 32rpx !important;
+					color: #2E64FA !important;
+				}
+			}
+		}
+	}
+
+	.row_gap {
+		background-color: #F8F9FD;
+		width: 100%;
+		height: 24rpx;
+	}
+	:deep(.search_tabs){
+		display: flex;
+		width: 100%;
+		flex-direction: column;
+		background-color: #FFFFFF;
+		.search_box {
+			display: flex;
+			align-items: center;
+			box-sizing: border-box;
+			width: 100%;
+			padding: 24rpx;
+			box-sizing: border-box;
+			background-color: #FFFFFF;
+		
+			.is-input-border {
+				border-radius: 8rpx;
+				border: 2rpx solid #DCDFE6;
+				border-color: #DCDFE6 !important;
+			}
+		
+			.search_icon {
+				width: 32rpx;
+				height: 32rpx;
+				margin-left: 24rpx;
+			}
+		
+			.uni-easyinput__content-input {
+				padding-left: 8rpx !important;
+				font-size: 28rpx;
+				color: #333333;
+				height: 72rpx;
+			}
+		}
+	}
+
+	.scroll_tabs {
+		margin-top:0;
+		background-color: #FFFFFF;
+	}
+
+	.total {
+		width: 100%;
+		display: flex;
+		font-weight: 400;
+		font-size: 28rpx;
+		color: #333333;
+		padding: 24rpx 0;
+		border-bottom: 2rpx solid #F3F3F3;
+	}
+
+	.list_item {
+		display: flex;
+		flex-direction: column;
+		width: 100%;
+		padding: 24rpx 0;
+		border-bottom: 2rpx solid #F3F3F3;
+		
+	}
+	.no_data{
+		margin-top: 24rpx;
+	}
+</style>

+ 1 - 1
pages/message/index.vue

@@ -11,7 +11,7 @@
 					<view class="message_left">
 					<view class="message_left">
 						<view class="message_info">
 						<view class="message_info">
 							<view class="message_title_row">
 							<view class="message_title_row">
-								<image src="/static/image/todo/daiban.png" class="message_icon" mode="aspectFit"></image>
+								<image src="@/static/image/todo/daiban.png" class="message_icon" mode="aspectFit"></image>
 								<text class="message_name">{{ item.taskName }}</text>
 								<text class="message_name">{{ item.taskName }}</text>
 							</view>
 							</view>
 							<view class="message_meta">
 							<view class="message_meta">

+ 1 - 1
pages/notice/mine/detail.vue

@@ -41,7 +41,7 @@
 				<view class="modal_list_wrapper">
 				<view class="modal_list_wrapper">
 					<scroll-view scroll-y class="modal_list">
 					<scroll-view scroll-y class="modal_list">
 						<view class="attachment_item" v-for="(file, index) in noticeDetail.noticeFiles" :key="index">
 						<view class="attachment_item" v-for="(file, index) in noticeDetail.noticeFiles" :key="index">
-							<image class="file_icon" src="/static/image/icon/file.png" mode="aspectFit"></image>
+							<image class="file_icon" src="@/static/image/icon/file.png" mode="aspectFit"></image>
 							<view class="file_info">
 							<view class="file_info">
 								<text class="file_name">{{ file.attachmentName }}</text>
 								<text class="file_name">{{ file.attachmentName }}</text>
 							</view>
 							</view>

+ 1 - 1
pages/notice/mine/index.vue

@@ -10,7 +10,7 @@
 						<view class="notice_title_row">
 						<view class="notice_title_row">
 							<image class="notice_icon" :src="item.icon" mode="aspectFit"></image>
 							<image class="notice_icon" :src="item.icon" mode="aspectFit"></image>
 							<text class="notice_title">{{ item.title }}</text>
 							<text class="notice_title">{{ item.title }}</text>
-							<image src="/static/image/icon/xiala.png" class="arrow_icon"></image>
+							<image src="@/static/image/icon/xiala.png" class="arrow_icon"></image>
 						</view>
 						</view>
 						<view class="notice_meta">
 						<view class="notice_meta">
 							<view class="meta_left">
 							<view class="meta_left">

+ 1 - 1
pages/notice/overview/noticeDetail.vue

@@ -35,7 +35,7 @@
 					</view>
 					</view>
 
 
 					<view class="search_box">
 					<view class="search_box">
-						<image src="/static/image/overview/search.png" class="search_icon"></image>
+						<image src="@/static/image/overview/search.png" class="search_icon"></image>
 						<input type="text" class="search_input" placeholder="请输入关键字搜索"
 						<input type="text" class="search_input" placeholder="请输入关键字搜索"
 							placeholder-class="search_placeholder" v-model="searchWord" @input="handleSearch" />
 							placeholder-class="search_placeholder" v-model="searchWord" @input="handleSearch" />
 					</view>
 					</view>

+ 1 - 1
pages/studentStudy/index.vue

@@ -12,7 +12,7 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-	import pageTabbar from '@/components/pageTabbar.vue';//头部
+	import pageTabbar from '@/components/pageTabbar.vue';//底部tabbar
 	import courseCenter from './courseCenter/index.vue';//课程中心
 	import courseCenter from './courseCenter/index.vue';//课程中心
 	import myLearning from './myLearning/index.vue';//我的学习
 	import myLearning from './myLearning/index.vue';//我的学习
 	import learningMonitor from './learningMonitor/index.vue';//学习监控
 	import learningMonitor from './learningMonitor/index.vue';//学习监控

+ 4 - 4
pages/studentStudy/learningMonitor/taskDetails.vue

@@ -9,7 +9,7 @@
 				<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
 				<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
 					:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
 					:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
 					<template #left>
 					<template #left>
-						<image src="/static/image/overview/search.png" class="search_icon"></image>
+						<image src="@/static/image/overview/search.png" class="search_icon"></image>
 					</template>
 					</template>
 				</uni-easyinput>
 				</uni-easyinput>
 				<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
 				<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
@@ -92,7 +92,7 @@
 					<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
 					<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
 						:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
 						:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
 						<template #left>
 						<template #left>
-							<image src="/static/image/overview/search.png" class="search_icon"></image>
+							<image src="@/static/image/overview/search.png" class="search_icon"></image>
 						</template>
 						</template>
 					</uni-easyinput>
 					</uni-easyinput>
 					<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
 					<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
@@ -174,11 +174,11 @@
 		id: '', //任务id
 		id: '', //任务id
 		courseType: '', //学习场景
 		courseType: '', //学习场景
 		searchWord: '', //搜索关键词
 		searchWord: '', //搜索关键词
-		searchInputStyles: { //搜框样式
+		searchInputStyles: { //搜框样式
 			borderColor: '#DCDFE6',
 			borderColor: '#DCDFE6',
 			color: '#333333'
 			color: '#333333'
 		},
 		},
-		searchInputPlaceholderStyle: 'color: #C0C4CC;fontSize: 28rpx', //搜框样式
+		searchInputPlaceholderStyle: 'color: #C0C4CC;fontSize: 28rpx', //搜框样式
 		tabsSelected: '', //默认选中tab值
 		tabsSelected: '', //默认选中tab值
 		tabList: [], //tab列表
 		tabList: [], //tab列表
 		mustTabList: [{
 		mustTabList: [{

+ 0 - 1
pages/studentStudy/myLearning/index.vue

@@ -356,6 +356,5 @@
 				}
 				}
 			}
 			}
 		}
 		}
-		
 	}
 	}
 </style>
 </style>

+ 1 - 1
pages/teacherHonor/honorAudit/teacherDetail.vue

@@ -38,7 +38,7 @@
 				</view>
 				</view>
 			</view>
 			</view>
 		</view>
 		</view>
-		<view class="page_foot" v-if="pageFoot=='1'">
+		<view class="page_foot" v-if="state.pageFoot=='1'">
 			<button v-if="state.reviewDetail?.honorStatus != 2" class="btn btn_reject" type="primary" plain="true" :loading="state.loading" @click="HandleRejectHonor">驳回</button>
 			<button v-if="state.reviewDetail?.honorStatus != 2" class="btn btn_reject" type="primary" plain="true" :loading="state.loading" @click="HandleRejectHonor">驳回</button>
 			<button v-if="state.reviewDetail?.honorStatus != 1" class="btn btn_pass" type="primary" :loading="state.loading" @click="HandlePassHonor">通过</button>
 			<button v-if="state.reviewDetail?.honorStatus != 1" class="btn btn_pass" type="primary" :loading="state.loading" @click="HandlePassHonor">通过</button>
 		</view>
 		</view>

+ 2 - 2
pages/teacherHonor/honorOverview/honorTypeAuditDetail.vue

@@ -72,11 +72,11 @@
 			value:'2',
 			value:'2',
 		}],
 		}],
 		searchWord:'',//搜索
 		searchWord:'',//搜索
-		searchInputStyles: { //搜框样式
+		searchInputStyles: { //搜框样式
 			borderColor: '#DCDFE6',
 			borderColor: '#DCDFE6',
 			color: '#333333'
 			color: '#333333'
 		},
 		},
-		searchInputPlaceholderStyle: 'color: #C0C4CC;fontSize: 28rpx', //搜框样式
+		searchInputPlaceholderStyle: 'color: #C0C4CC;fontSize: 28rpx', //搜框样式
 		pageLists:[],//全部数据
 		pageLists:[],//全部数据
 		pageList:[],//列表数据
 		pageList:[],//列表数据
 		honorTypeId: '',//荣誉类型id
 		honorTypeId: '',//荣誉类型id

+ 1 - 1
pages/teacherHonor/honorOverview/honorTypeDetail.vue

@@ -7,7 +7,7 @@
 				<uni-forms-item label="类型名称:">
 				<uni-forms-item label="类型名称:">
 					<uni-easyinput v-model="state.formData.honorTypeName" :maxlength="30" placeholder="请输入类型名称" />
 					<uni-easyinput v-model="state.formData.honorTypeName" :maxlength="30" placeholder="请输入类型名称" />
 				</uni-forms-item>
 				</uni-forms-item>
-				<uni-forms-item label="审核机制:">
+				<uni-forms-item label="审核机制:" style="align-items: center;">
 					<uni-data-checkbox v-model="state.formData.reviewStatus" selectedColor="#2E64FA" selectedTextColor="#333333" :localdata="state.radioList"></uni-data-checkbox>
 					<uni-data-checkbox v-model="state.formData.reviewStatus" selectedColor="#2E64FA" selectedTextColor="#333333" :localdata="state.radioList"></uni-data-checkbox>
 				</uni-forms-item>
 				</uni-forms-item>
 				<uni-forms-item label="审核人:" v-if="state.formData.reviewStatus===0">
 				<uni-forms-item label="审核人:" v-if="state.formData.reviewStatus===0">

+ 2 - 2
pages/teacherHonor/honorOverview/index.vue

@@ -53,14 +53,14 @@
 		<view class="popup_content">
 		<view class="popup_content">
 			<view class="content_item" @click="AddEditHonorType('edit')">
 			<view class="content_item" @click="AddEditHonorType('edit')">
 				<view class="content_item_left">
 				<view class="content_item_left">
-					<image class="img" src="/static/image/icon/edit.png"></image>
+					<image class="img" src="@/static/image/icon/edit.png"></image>
 					<text class="text">编辑</text>
 					<text class="text">编辑</text>
 				</view>
 				</view>
 				<uni-icons class="content_item_right" type="right" style="color: #333333;font-size: 36rpx;"></uni-icons>
 				<uni-icons class="content_item_right" type="right" style="color: #333333;font-size: 36rpx;"></uni-icons>
 			</view>
 			</view>
 			<view class="content_item" v-if="state.popupDelDialog.deleteStatus!=1" @click="DeleteHonorTypeItem">
 			<view class="content_item" v-if="state.popupDelDialog.deleteStatus!=1" @click="DeleteHonorTypeItem">
 				<view class="content_item_left">
 				<view class="content_item_left">
-					<image class="img" src="/static/image/icon/delete.png"></image>
+					<image class="img" src="@/static/image/icon/delete.png"></image>
 					<text :class="['text',{'red':state.popupDelDialog.deleteStatus!=1,'disabled':state.popupDelDialog.deleteStatus==1}]">删除</text>
 					<text :class="['text',{'red':state.popupDelDialog.deleteStatus!=1,'disabled':state.popupDelDialog.deleteStatus==1}]">删除</text>
 				</view>
 				</view>
 			</view>
 			</view>

+ 1 - 1
pages/teacherHonor/index.vue

@@ -14,7 +14,7 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-	import pageTabbar from '@/components/pageTabbar.vue';//头部
+	import pageTabbar from '@/components/pageTabbar.vue';//底部tabbar
 	import honorOverview from './honorOverview/index.vue';//荣誉总览
 	import honorOverview from './honorOverview/index.vue';//荣誉总览
 	import honorTeacher from './honorTeacher/index.vue';//荣誉教师
 	import honorTeacher from './honorTeacher/index.vue';//荣誉教师
 	import myHonor from './myHonor/index.vue';//我的荣誉
 	import myHonor from './myHonor/index.vue';//我的荣誉

+ 1 - 1
pages/teacherStudy/index.vue

@@ -12,7 +12,7 @@
 </template>
 </template>
 
 
 <script setup>
 <script setup>
-	import pageTabbar from '@/components/pageTabbar.vue';//头部
+	import pageTabbar from '@/components/pageTabbar.vue';//底部tabbar
 	import courseCenter from './courseCenter/index.vue';//课程中心
 	import courseCenter from './courseCenter/index.vue';//课程中心
 	import myLearning from './myLearning/index.vue';//我的研修
 	import myLearning from './myLearning/index.vue';//我的研修
 	import learningMonitor from './learningMonitor/index.vue';//研修监控
 	import learningMonitor from './learningMonitor/index.vue';//研修监控

+ 4 - 4
pages/teacherStudy/learningMonitor/taskDetails.vue

@@ -9,7 +9,7 @@
 				<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
 				<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
 					:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
 					:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
 					<template #left>
 					<template #left>
-						<image src="/static/image/overview/search.png" class="search_icon"></image>
+						<image src="@/static/image/overview/search.png" class="search_icon"></image>
 					</template>
 					</template>
 				</uni-easyinput>
 				</uni-easyinput>
 				<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
 				<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
@@ -92,7 +92,7 @@
 					<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
 					<uni-easyinput class="search_box" v-model="state.searchWord" trim="all" :styles="state.searchInputStyles"
 						:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
 						:placeholderStyle="state.searchInputPlaceholderStyle" placeholder="请输入关键字搜索" @input="HandleSearchInput">
 						<template #left>
 						<template #left>
-							<image src="/static/image/overview/search.png" class="search_icon"></image>
+							<image src="@/static/image/overview/search.png" class="search_icon"></image>
 						</template>
 						</template>
 					</uni-easyinput>
 					</uni-easyinput>
 					<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
 					<scroll-view class="scroll_tabs" scroll-x="true" scroll-left="0" :show-scrollbar="false">
@@ -174,11 +174,11 @@
 		id: '', //任务id
 		id: '', //任务id
 		courseType: '', //研修场景
 		courseType: '', //研修场景
 		searchWord: '', //搜索关键词
 		searchWord: '', //搜索关键词
-		searchInputStyles: { //搜框样式
+		searchInputStyles: { //搜框样式
 			borderColor: '#DCDFE6',
 			borderColor: '#DCDFE6',
 			color: '#333333'
 			color: '#333333'
 		},
 		},
-		searchInputPlaceholderStyle: 'color: #C0C4CC;fontSize: 28rpx', //搜框样式
+		searchInputPlaceholderStyle: 'color: #C0C4CC;fontSize: 28rpx', //搜框样式
 		tabsSelected: '', //默认选中tab值
 		tabsSelected: '', //默认选中tab值
 		tabList: [], //tab列表
 		tabList: [], //tab列表
 		mustTabList: [{
 		mustTabList: [{

+ 3 - 7
pages/workspace/index.vue

@@ -112,7 +112,7 @@
 					</view>
 					</view>
 				</view>
 				</view>
 				<view class="add_schedule_btn" @click="handleAddSchedule">
 				<view class="add_schedule_btn" @click="handleAddSchedule">
-					<image src="/static/image/workspace/add_icon.png" class="add_icon" mode="aspectFit"></image>
+					<image src="@/static/image/workspace/add_icon.png" class="add_icon" mode="aspectFit"></image>
 					<text class="btn_text">新增日程</text>
 					<text class="btn_text">新增日程</text>
 				</view>
 				</view>
 			</view>
 			</view>
@@ -123,7 +123,7 @@
 				<view class="modal-header">
 				<view class="modal-header">
 					<text class="modal-title">新增日程</text>
 					<text class="modal-title">新增日程</text>
 					<view class="modal-close" @click="handleCloseModal">
 					<view class="modal-close" @click="handleCloseModal">
-						<image src="/static/image/workspace/close.png" class="close-icon" mode="aspectFit"></image>
+						<image src="@/static/image/workspace/close.png" class="close-icon" mode="aspectFit"></image>
 					</view>
 					</view>
 				</view>
 				</view>
 				<view class="modal-body">
 				<view class="modal-body">
@@ -362,11 +362,7 @@ const handleSystemClick = (item) => {
 				url: '/pages/notice/mine/index?hideTabbar=true'
 				url: '/pages/notice/mine/index?hideTabbar=true'
 			});
 			});
 		}
 		}
-	} 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 === 'materialCollection' || item.key == 'teacherStudy' || item.key == 'studentStudy' || item.key == 'teacherHonor') {//材料采集 教师研修 学生学习 教师发展 
 		uni.navigateTo({
 		uni.navigateTo({
 			url: `/pages/${item.key}/index`
 			url: `/pages/${item.key}/index`
 		});
 		});

+ 2 - 2
pages/workspace/schedule.vue

@@ -46,7 +46,7 @@
 				<text class="schedule_date">{{ selectedDate }}</text>
 				<text class="schedule_date">{{ selectedDate }}</text>
 				<view class="add_btn" @click="handleAddSchedule">
 				<view class="add_btn" @click="handleAddSchedule">
 					<!-- <uni-icons type="‌plus-filled" size="24" color="#fff"></uni-icons> -->
 					<!-- <uni-icons type="‌plus-filled" size="24" color="#fff"></uni-icons> -->
-					<image src="/static/image/workspace/add.png" class="add_icon" mode="aspectFit"></image>
+					<image src="@/static/image/workspace/add.png" class="add_icon" mode="aspectFit"></image>
 					<text>新增日程</text>
 					<text>新增日程</text>
 				</view>
 				</view>
 			</view>
 			</view>
@@ -72,7 +72,7 @@
 				<view class="modal-header">
 				<view class="modal-header">
 					<text class="modal-title">{{ editItem ? '编辑日程' : '新增日程' }}</text>
 					<text class="modal-title">{{ editItem ? '编辑日程' : '新增日程' }}</text>
 					<view class="modal-close" @click="handleCloseModal">
 					<view class="modal-close" @click="handleCloseModal">
-						<image src="/static/image/workspace/close.png" class="close-icon" mode="aspectFit"></image>
+						<image src="@/static/image/workspace/close.png" class="close-icon" mode="aspectFit"></image>
 					</view>
 					</view>
 				</view>
 				</view>
 				<view class="modal-body">
 				<view class="modal-body">

+ 51 - 23
reqApi/notification.js

@@ -1,26 +1,54 @@
 import request from '@/common/request.js';
 import request from '@/common/request.js';
 
 
-const notification = {
-	// 学年学期列表
-	getSchoolYearList() {
-		return request.get('/api/v1/teaching_plan/collect/target_loading/find_school_year')
-	},
-    // 归属分类
-    getCategoryList() {
-        return request.get('/api/v1/teaching_plan/collect/file_category/file_category_data')
-    },
-    // 总览列表
-    find_collection_task(data) {
-        return request.post('/api/v1/teaching_plan/collect/collection_task/find_collection_task', data)
-    },
-    // 提交材料列表
-    find_teacher_task_target_list(data) {
-        return request.post('/api/v1/teaching_plan/collect/task_target/find_teacher_task_target_list', data)
-    },
-    // 审核人列表
-    getAuditorList(data) {
-        return request.get(`/api/v1/teaching_plan/collect/target_loading/query_teacher_info?accountName=${data}`)
-    },
+// 获取当前登录人的菜单显示
+export const queryTaskMenu = () => {
+	return request.get('/api/v1/teaching_plan/collect/collection_task/query_task_menu')
 }
 }
-
-export default notification
+// 学年学期列表
+export const getSchoolYearList = () => {
+	return request.get('/api/v1/teaching_plan/collect/target_loading/find_school_year')
+}
+// 归属分类
+export const getCategoryList = () => {
+	return request.get('/api/v1/teaching_plan/collect/file_category/file_category_data')
+}
+// 总览列表
+export const findCollectionTask = (data) => {
+	return request.post('/api/v1/teaching_plan/collect/collection_task/find_collection_task', data)
+}
+//删除采集任务
+export const deleteCollectionTask = (taskId) => {
+	return request.post(`/api/v1/teaching_plan/collect/collection_task/delete_collection_task?taskId=${taskId}`)
+}
+// 提交材料列表
+export const findTeacherTaskTargetList = (data) => {
+	return request.post('/api/v1/teaching_plan/collect/task_target/find_teacher_task_target_list', data)
+}
+// 审核人列表
+export const queryTeacherInfo = (data) => {
+	return request.get(`/api/v1/teaching_plan/collect/target_loading/query_teacher_info?accountName=${data}`)
+}
+// 审核的任务列表
+export const getTaskTargetReview = (data) => {
+	return request.post('/api/v1/teaching_plan/collect/task_target_review/get_task_target_review', data)
+}
+// 获取任务详情,用于编辑采集任务
+export const getCollectionTaskInfo = (taskId) => {
+	return request.post(`/api/v1/teaching_plan/collect/collection_task/get_collection_task_info?taskId=${taskId}`)
+}
+// 新建采集任务
+export const insertCollectionTask = (data) => {
+	return request.post('/api/v1/teaching_plan/collect/collection_task/insert_collection_task',data)
+}
+// 更新采集任务
+export const UpdateCollectionTask = (data) => {
+	return request.post('/api/v1/teaching_plan/collect/collection_task/update_collection_task',data)
+}
+// 获取指定的采集任务详情
+export const GetCollectionTask = (data) => {
+  return request.get(`/api/v1/teaching_plan/collect/collection_task/get_collection_task?taskId=${data}`)
+}
+// 获取当前采集任务具体采集详情列表
+export const getTaskTargetList = (data) => {
+  return request.post('/api/v1/teaching_plan/collect/Task_statistics_info/get_task_target_list',data)
+}

BIN
static/image/icon/CursorUserSetup-x64-3.15.6.exe


+ 7 - 0
style/common.scss

@@ -171,6 +171,7 @@ uni-page-body {
 			.text {
 			.text {
 				display: inline-flex;
 				display: inline-flex;
 				align-items: center;
 				align-items: center;
+				gap: 6rpx;
 				.color_999 {
 				.color_999 {
 					color: #999999;
 					color: #999999;
 					margin: 0 4rpx;
 					margin: 0 4rpx;
@@ -504,6 +505,9 @@ uni-page-body {
 	height: 56rpx;
 	height: 56rpx;
 	padding: 0 24rpx;
 	padding: 0 24rpx;
 	box-sizing: border-box;
 	box-sizing: border-box;
+	.scroll_tabs_view{
+		flex:1;
+	}
 	.uni-scroll-view-content {
 	.uni-scroll-view-content {
 		display: flex;
 		display: flex;
 		gap: 48rpx;
 		gap: 48rpx;
@@ -648,6 +652,9 @@ uni-page-body {
 						color: #909399 ;
 						color: #909399 ;
 					}
 					}
 				}
 				}
+				.uni-easyinput__content-textarea{
+					padding-left:24rpx !important;
+				}
 				.content-clear-icon {
 				.content-clear-icon {
 					font-size: 40rpx !important;
 					font-size: 40rpx !important;
 					padding: 0 10rpx;
 					padding: 0 10rpx;