1
0

2 Коммиты 4ffbc83eab ... 157d6d62a1

Автор SHA1 Сообщение Дата
  liurongli 157d6d62a1 材料采集 4 дней назад
  liurongli affaa3e991 材料采集 4 дней назад

+ 1 - 1
components/popupPreviewFile.vue

@@ -1,5 +1,5 @@
 <template>
-	<uni-popup ref="popupDialog" :is-mask-click="isMaskClick">
+	<uni-popup ref="popupDialog" :animation="false" :is-mask-click="isMaskClick">
 		<uni-icons @click="CloseDialog" class="colse" type="closeempty" size="24"></uni-icons>
 		<image class="img_width" @click="CloseDialog" :src="filePath" mode="aspectFit"></image>
 	</uni-popup>	

+ 9 - 2
pages.json

@@ -247,14 +247,14 @@
 			}
 		},
 		{
-			"path": "pages/materialCollection/taskOverview/components/selectObjectNoDedup",
+			"path": "pages/materialCollection/taskOverview/selectObjectNoDedup",
 			"style": {
 				"navigationBarTitleText": "选择通知对象",
 				"navigationStyle": "custom"
 			}
 		},
 		{
-			"path": "pages/materialCollection/taskOverview/components/personList",
+			"path": "pages/materialCollection/taskOverview/personList",
 			"style": {
 				"navigationBarTitleText": "人员列表",
 				"navigationStyle": "custom"
@@ -280,6 +280,13 @@
 				"navigationBarTitleText": "审核材料-审核详情",
 				"navigationStyle": "custom"
 			}
+		},
+		{
+			"path": "pages/materialCollection/reviewMaterial/auditResult",
+			"style": {
+				"navigationBarTitleText": "审核材料-审核详情-审核",
+				"navigationStyle": "custom"
+			}
 		}
 	],
 	"easycom": {

+ 18 - 3
pages/materialCollection/reviewMaterial/auditDetail.vue

@@ -44,7 +44,7 @@
 							<text class="time_item" v-if="remainingDays(state?.details?.endTime) > 0">剩余{{remainingDays(state?.details?.endTime)}}天</text>
 						</view>
 						<view :class="['task_status', statusClassMap[state?.details?.taskStatus]]">
-							{{taskStatusMap[state?.details.taskStatus]}}
+							{{taskStatusMap[state?.details?.taskStatus]}}
 						</view>
 					</view>
 					<view :class="['task_desc',{'over':!state.isExpand}]">
@@ -78,7 +78,7 @@
 									<text class="name">{{item.targetName}}</text>
 									<text class="file_num">文件数量:{{item?.taskTargetFileVos?.length || 0}}</text>
 								</view>
-								<view class="btn">{{state.tabsSelected>0?'查看':'审核'}}</view>
+								<view class="btn" @click="handleAudit(item)">{{state.tabsSelected>0?'查看':'审核'}}</view>
 							</view>
 							<view class="item_info">
 								<text class="info_text">{{item.showInfo}}</text>
@@ -103,7 +103,8 @@
 	import { remainingDays } from '@/common/common.js';
 	import {getReviewTaskList} from '@/reqApi/notification.js';
 	import {
-		onLoad
+		onLoad,
+		onShow
 	} from '@dcloudio/uni-app';
 	import {
 		reactive,
@@ -149,6 +150,12 @@
 		1: '进行中',
 		2: '已结束'
 	};
+	onShow(()=>{
+		const isLoadReviewMaterialDetailList = uni.getStorageSync('isLoadReviewMaterialDetailList');
+		if(isLoadReviewMaterialDetailList){//审核驳回通过返回刷新列表
+			OnLoadData(true);
+		}
+	})
 	onLoad((option) => {
 		state.taskId = option.taskId;
 	})
@@ -157,6 +164,7 @@
 		OnLoadData(true,true); // 数据加载完成后触发 checkTextOverflow
 	});
 	onUnmounted(() => {
+		// uni.removeStorageSync('isLoadReviewMaterialDetailList');//移除缓存
 		uni.removeStorageSync('collectReviewDetailInfo');//移除缓存
 	})
 	const checkTextOverflow = () => {
@@ -291,6 +299,13 @@
 			state.scrollTop = 0
 		});
 	}
+	//去审核
+	const handleAudit = (item) => {
+		uni.setStorageSync('reviewMaterialDetailData', item);//详情数据
+		uni.navigateTo({
+			url: `/pages/materialCollection/reviewMaterial/auditResult?taskStatus=${state?.details.taskStatus}`
+		});
+	};
 	//返回
 	const GoBack = () => {
 		uni.navigateBack({

+ 194 - 0
pages/materialCollection/reviewMaterial/auditResult.vue

@@ -0,0 +1,194 @@
+<template>
+	<view class="page_body">
+		<!-- 头部 -->
+		<nav-bar height="216" :title="state.pageTitle" :onlyTitle="false" :showHeadSearchInput="false" :showFilterPicker="false" :showTabs="false" :showTabBtns="true" :tabBtns="state.tabBtns" rightWidth="0rpx" @GoBack="GoBack"></nav-bar>
+		<view class="page_content">
+			
+		</view>
+		<view class="page_foot">
+			<button :class="['btn','btn_reject',{'disabled':state.taskStatus==2 || (state.taskStatus==1 && state.reviewStatus == 2)}]" type="primary" plain="true" :loading="state.loading" @click="HandleRejectHonor">驳回</button>
+			<button :class="['btn','btn_pass',{'disabled':state.taskStatus==2 || (state.taskStatus==1 && state.reviewStatus == 1)}]" type="primary" :loading="state.loading" @click="HandlePassHonor">通过</button>
+		</view>
+		<customPopupDialog ref="popupDelDialogRef" title="驳回" dialogWidth="702" :isMaskClick="false" :showDialogClose="false" @DialogConfirm="DialogConfirm">
+			<view class="dialog_content_input">
+				<view class="dialog_desc">请填写驳回原因方便教师修改</view>
+				<uni-easyinput type="textarea" v-model="state.rejectReason" :maxlength="200" :style="state.easyinputStyle" placeholderStyle="font-weight: 400;font-size: 28rpx;color: #999999;" placeholder="请输入驳回原因…"></uni-easyinput>
+			</view>
+		</customPopupDialog>
+	</view>
+</template>
+
+<script setup>
+	import navBar from '@/components/navBar.vue';
+	import uvUpload from '@/uni_modules/uv-upload/components/uv-upload/uv-upload.vue';
+	import customPopupDialog from '@/components/customPopupDialog.vue';
+	import uniEasyinput from '@/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue';
+	import {updateReviewStatus,ChangeReviewStatus} from '@/reqApi/notification.js';
+	import {
+		reactive,
+		ref,
+		nextTick,
+		onUnmounted
+	} from 'vue';
+	import { onLoad } from '@dcloudio/uni-app';
+	const state = reactive({
+		taskStatus:'',
+		reviewStatus:'',
+		taskTargetId:'',
+		loading:false,
+		pageTitle:'',
+		tabBtns:[],
+		rejectReason:'',//驳回原因
+		easyinputStyle:{
+			color: '#303133',
+			borderColor: '#E9E9E9'
+		}
+	})
+	const popupDelDialogRef = ref(null);
+	onLoad((option) => {
+		state.taskStatus = Number(option.taskStatus);//任务状态
+		uni.removeStorageSync('isLoadReviewMaterialDetailList');//是否更新列表
+		const detailData = uni.getStorageSync('reviewMaterialDetailData');//数据
+		state.pageTitle = detailData?.targetName || '';
+		state.reviewStatus = detailData?.reviewStatus || '';//审核状态
+		state.taskTargetId = detailData?.taskTargetId || '';
+		const fileList = detailData?.taskTargetFileVos || [];
+		state.tabBtns = fileList.map(item=>({
+			...item,
+			label:item.fileName,
+			value:item.id,
+		}))
+		console.log(detailData,32323)
+		
+	})
+	onUnmounted(()=>{
+		uni.removeStorageSync('reviewMaterialDetailData');//删除缓存数据
+	})
+	//通过
+	const HandlePassHonor = () => {
+		if(state.taskStatus==2 || (state.taskStatus==1 && state.reviewStatus == 1)){
+			return false
+		}
+		HandleRejectOrPass(1)
+	}
+	//驳回
+	const HandleRejectHonor = () => {
+		if(state.taskStatus==2 || (state.taskStatus==1 && state.reviewStatus == 2)){
+			return false
+		}
+		popupDelDialogRef.value.OpenDialog();
+	}
+	//驳回 确定按钮
+	const DialogConfirm = () => {
+		if(state.rejectReason == '' || state.rejectReason == null){
+			uni.showToast({
+				title: '请填写驳回原因!',
+				icon: 'none'
+			})
+			return false
+		}
+		HandleRejectOrPass(2)
+	}
+	const HandleRejectOrPass = (status) => {
+		const params = {
+			taskTargetId: state.taskTargetId,
+			reviewStatus: status
+		}
+		if(status == 2){
+			params.reviewContent = state.rejectReason;
+		}
+		const apiFn = state.reviewStatus === 0 ? updateReviewStatus : ChangeReviewStatus;
+		apiFn(params).then(res=>{
+			if(res.code == 200){
+				uni.showToast({
+					title: status == 2?'驳回成功!':'审核通过!',
+					icon: 'none'
+				})
+				uni.setStorageSync('isLoadReviewMaterialDetailList', true);//刷新荣誉审核列表
+				GoBack();
+			}
+		})
+	}
+	const GoBack = () => {
+		uni.navigateBack({
+			delta: 1
+		});
+	}
+</script>
+
+<style lang="scss" scoped>
+	.page_body{
+		height: 100%;
+		min-height: auto;
+	}
+	.page_content{
+		height: calc(100% - 390rpx);
+		overflow: auto;
+	}
+	.page_foot{
+		position: fixed;
+		left:0;
+		right: 0;
+		bottom: 0;
+		padding: 40rpx 24rpx 38rpx 24rpx;
+		box-shadow: inset 0px 2rpx 0px 0px #F3F3F3;
+		background-color:#FFFFFF;
+		gap: 30rpx;
+		display: flex;
+		.btn{
+			height: 90rpx;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			border-radius: 8rpx;
+			font-weight: 500;
+			font-size: 28rpx;
+			flex: 1;
+			box-sizing: border-box;
+		}
+		.btn_reject{
+			border: 2rpx solid #F56C6C;
+			color: #F56C6C;
+			&.disabled{
+				border: 2rpx solid #C0C4CC;
+				color: #C0C4CC;
+			}
+		}
+		.btn_pass{
+			background-color: #2E64FA !important;
+			color: #FFFFFF;
+			&.disabled{
+				background-color: #F3F3F3 !important;
+				color: #C0C4CC;
+			}
+		}
+	}
+	.dialog_content_input{
+		width: 100%;
+		display: flex;
+		flex-direction: column;
+		box-sizing: border-box;
+		.dialog_desc{
+			font-weight: 400;
+			font-size: 32rpx;
+			color: #303133;
+		}
+		:deep(.uni-easyinput){
+			margin-top: 20rpx;
+			font-size: 28rpx;
+			.is-input-border{
+				border-radius: 8rpx;
+				border-color: #E9E9E9 !important;
+			}
+			.uni-easyinput__content-textarea{
+				height: 400rpx;
+				min-height: 400rpx;
+				font-size: 28rpx;
+				margin:20rpx 24rpx 20rpx 14rpx;
+			}
+			.input-padding{
+				padding-left: 10rpx;
+			}
+		}
+	}
+</style>

+ 11 - 1
pages/materialCollection/reviewMaterial/index.vue

@@ -69,7 +69,8 @@
 </template>
 
 <script setup>
-import { reactive,ref,nextTick, onMounted } from 'vue';
+import { reactive,ref,nextTick, onMounted,onUnmounted } from 'vue';
+import {onShow} from '@dcloudio/uni-app';
 import navBar from '@/components/navBar.vue';
 import {getTaskTargetReview,getSchoolYearList,getCategoryList} from '@/reqApi/notification.js';
 import { truncateText,remainingDays } from '@/common/common.js';
@@ -311,11 +312,20 @@ const handleDetail = (item) => {
 		url: `/pages/materialCollection/reviewMaterial/auditDetail?taskId=${item.id}`
 	});
 };
+onShow(()=>{
+	const isLoadReviewMaterialDetailList = uni.getStorageSync('isLoadReviewMaterialDetailList');
+	if(isLoadReviewMaterialDetailList){//审核驳回通过返回刷新列表
+		OnLoadData(true);
+	}
+})
 onMounted(async () => {
 	await fetchSchoolYearList();//学年学期列表
 	fetchCategoryList();//归属分类
 	OnLoadData(true);
 });
+onUnmounted(() => {
+	uni.removeStorageSync('isLoadReviewMaterialDetailList');//移除缓存
+})
 </script>
 
 <style lang="scss" scoped>

+ 256 - 248
pages/materialCollection/submitMaterial/index.vue

@@ -69,265 +69,273 @@
 </template>
 
 <script setup>
-import { reactive,ref,nextTick, onMounted,onUnmounted } from 'vue';
-import navBar from '@/components/navBar.vue';
-import {findTeacherTaskTargetList,getSchoolYearList,getCategoryList} from '@/reqApi/notification.js';
-import { truncateText,remainingDays } from '@/common/common.js';
+	import { reactive,ref,nextTick, onMounted,onUnmounted } from 'vue';
+	import navBar from '@/components/navBar.vue';
+	import {onShow} from '@dcloudio/uni-app';
+	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 = {
-	0: 'status_pending',
-	1: 'status_published',
-	2: 'status_closed'
-};
-const taskStatusMap = {
-	0: '待开始',
-	1: '进行中',
-	2: '已结束'
-}
-const tabStatusClassMap = {
-	'notSubmitList':'待提交',    // 待提交
-	'notReviewList':'审核中',     // 审核中
-	'reviewReasonList':'已驳回',      // 已驳回
-	'reviewList':'已提交'      // 已提交
-};
-// 学年学期列表
-const fetchSchoolYearList = async () => {
-	try {
-		const res = await getSchoolYearList();
-		if (res.data && Array.isArray(res.data)) {
-			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) {
-		console.error('获取学年学期列表失败:', error);
+	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 = {
+		0: 'status_pending',
+		1: 'status_published',
+		2: 'status_closed'
+	};
+	const taskStatusMap = {
+		0: '待开始',
+		1: '进行中',
+		2: '已结束'
 	}
-};
-// 归属分类
-const fetchCategoryList = async () => {
-	try {
-		const res = await getCategoryList();
-		if (res.data && Array.isArray(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);
+	const tabStatusClassMap = {
+		'notSubmitList':'待提交',    // 待提交
+		'notReviewList':'审核中',     // 审核中
+		'reviewReasonList':'已驳回',      // 已驳回
+		'reviewList':'已提交'      // 已提交
+	};
+	// 学年学期列表
+	const fetchSchoolYearList = async () => {
+		try {
+			const res = await getSchoolYearList();
+			if (res.data && Array.isArray(res.data)) {
+				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) {
+			console.error('获取学年学期列表失败:', error);
 		}
-	} catch (error) {
-		console.error('获取分类列表失败:', error);
-	}
-};
-//切换条件选择器
-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:''
-				})
+	};
+	// 归属分类
+	const fetchCategoryList = async () => {
+		try {
+			const res = await getCategoryList();
+			if (res.data && Array.isArray(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) {
+			console.error('获取分类列表失败:', error);
+		}
+	};
+	//切换条件选择器
+	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
 			}
-			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;//审核状态
 		}
-	}else if(type == 'search'){
-		state.params.taskName = searchWord;//任务名称
-	}else{
-		state.params.auditStatus = tabsSelected;//审核状态
+		OnLoadData(true);
 	}
-	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++;
+	//切换任务状态
+	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.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)
+			}, 0)
+		}
+	};
+	// 自定义下拉刷新被触发	 下拉刷新
+	const OnRefresh = () =>{
+		state.isRefreshing = true;//下拉刷新已经被触发
+		OnLoadData(true);
 	}
-};
-// 自定义下拉刷新被触发	 下拉刷新
-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 handleDetail = (item) => {
-	state.details = uni.setStorageSync('submitMaterialDetailInfo',item);
-	if(item?.taskTargetVos?.length > 1){
-		uni.navigateTo({
-			url: `/pages/materialCollection/submitMaterial/taskDetail?taskId=${item.id}&auditStatus=${state.params.auditStatus}`
-		});
-	}else{
-		const targetId = item?.taskTargetVos?.[0].id;
-		uni.navigateTo({
-			url: `/pages/materialCollection/submitMaterial/submitDetail?taskId=${item.id}&targetId=${targetId}`
+	//滚动到底部/右边 触发上拉刷新
+	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
 		});
 	}
-};
-onMounted(async () => {
-	await fetchSchoolYearList();//学年学期列表
-	fetchCategoryList();//归属分类
-	OnLoadData(true);
-});
-onUnmounted(() => {
-	uni.removeStorageSync('submitMaterialDetailInfo');//移除缓存
-})
+	//任务详情
+	const handleDetail = (item) => {
+		state.details = uni.setStorageSync('submitMaterialDetailInfo',item);
+		if(item?.taskTargetVos?.length > 1){
+			uni.navigateTo({
+				url: `/pages/materialCollection/submitMaterial/taskDetail?taskId=${item.id}&auditStatus=${state.params.auditStatus}`
+			});
+		}else{
+			const targetId = item?.taskTargetVos?.[0].id;
+			uni.navigateTo({
+				url: `/pages/materialCollection/submitMaterial/submitDetail?taskId=${item.id}&targetId=${targetId}`
+			});
+		}
+	};
+	onShow(()=>{
+		const isLoadSubmitMaterialIndex = uni.getStorageSync('isLoadSubmitMaterialIndex');//返回是否重新更新提交材料首页
+		if(isLoadSubmitMaterialIndex){
+			OnLoadData(true);
+		}
+	})
+	onMounted(async () => {
+		await fetchSchoolYearList();//学年学期列表
+		fetchCategoryList();//归属分类
+		OnLoadData(true);
+	});
+	onUnmounted(() => {
+		uni.removeStorageSync('submitMaterialDetailInfo');//移除缓存
+		uni.removeStorageSync('isLoadSubmitMaterialIndex');//返回是否重新更新提交材料首页
+	})
 </script>
 
 <style lang="scss" scoped>

+ 72 - 25
pages/materialCollection/submitMaterial/submitDetail.vue

@@ -130,7 +130,7 @@
 			</template>
 		</view>
 		<!-- 删除确认框 -->
-		<popupDialog ref="popupDelDialogRef" :showFootBorder="true" :content="state.delDialog.content" @DialogConfirm="DialogDelConfirm" />
+		<popupDialog ref="popupConfirmDialogRef" :showFootBorder="true" :content="state.confirmDialog.content" @DialogConfirm="DialogConfirm" />
 		<!-- 提示框 -->
 		<popupPreviewFile ref="popupDialogRef" :filePath="state.previewPopup.filePath"></popupPreviewFile>
 		<!-- 文件、图片下载 -->
@@ -158,11 +158,12 @@
 	const state = reactive({
 		taskId: '', //任务id
 		targetId:'',//
+		auditStatus:'',//审核状态
 		showExpandBtn: false, //是否显示展开按钮
 		isExpand: false, //是否展开
 		details: {}, //详情信息
 		targetFileList:{},
-		delDialog:{
+		confirmDialog:{
 			type:'',
 			content:'',
 			fileUrls:[],
@@ -172,7 +173,7 @@
 			filePath:''
 		}
 	});
-	const popupDelDialogRef = ref(null);
+	const popupConfirmDialogRef = ref(null);
 	const popupDialogRef = ref(null);
 	const fileUploader = ref(null);
 	const ssdownload = ref(null);
@@ -190,12 +191,15 @@
 	onLoad((option) => {
 		state.taskId = option.taskId;
 		state.targetId = option.targetId;
+		state.auditStatus = Number(option.auditStatus);
 	})
 	onMounted(() => {
 		state.details = uni.getStorageSync('submitMaterialDetailInfo') || {};
+		uni.removeStorageSync('isLoadSubmitMaterialTaskDetail');//返回是否重新更新任务详情数据
+		uni.removeStorageSync('isLoadSubmitMaterialIndex');//返回是否重新更新提交材料首页
 		getApiBaseUrl();//上传接口地址
 		checkTextOverflow();
-		GetTaskTargetFileList();
+		GetTaskTargetFileList(true);
 	});
 	//上传接口地址
 	const getApiBaseUrl = () => {
@@ -211,7 +215,6 @@
 		fileUploader.value.chooseFile({//选择上传文件
 			count: 1,
 			success: (files) => {
-				console.log(files[0])
 				fileUploader.value.upload({//上传单个文件
 					url:`${apiBaseUrl.value}/api/v1/teach/oss/file/oss/upload_file_list`,
 					file: files[0],
@@ -247,7 +250,7 @@
 					title: '上传成功!',
 					icon: 'none'
 				});
-				GetTaskTargetFileList();
+				GetTaskTargetFileList(false,'upload');
 			}
 		})
 	}
@@ -348,10 +351,15 @@
 		state.isExpand = !state.isExpand;
 	}
 	//获取当前教师提交的文件列表
-	const GetTaskTargetFileList = () => {
+	const GetTaskTargetFileList = (init,type) => {
 		getTaskTargetFileList(state.targetId).then(res=>{
 			if(res.code == 200){
 				state.targetFileList = res.data || {};
+				//对比审核状态是否发生变化同时更新缓存数据
+				if(!init){
+					uni.setStorageSync('isLoadSubmitMaterialIndex',true);//返回是否重新更新提交材料首页
+					updateCacheData(type);
+				}
 			}
 		})
 	}
@@ -361,13 +369,13 @@
 			return false
 		}
 		const { filePath, id } = item;
-		state.delDialog = {
+		state.confirmDialog = {
 			type:'del',
 			content:'是否删除当前文件?',
 			fileUrls:[filePath],
 			targetFileIds:[id]
 		};
-		popupDelDialogRef.value.OpenDialog();
+		popupConfirmDialogRef.value.OpenDialog();
 	}
 	//删除全部
 	const DeleteAllFiles = () => {
@@ -378,13 +386,13 @@
 				fileUrls.push(item.filePath);
 				targetFileIds.push(item.id)
 			})
-			state.delDialog = {
+			state.confirmDialog = {
 				type:'del',
 				content:'是否删除全部当前文件?',
 				fileUrls:fileUrls,
 				targetFileIds:targetFileIds
 			};
-			popupDelDialogRef.value.OpenDialog();
+			popupConfirmDialogRef.value.OpenDialog();
 		}
 	}
 	//提交
@@ -397,34 +405,34 @@
 			});
 			return false
 		}
-		state.delDialog = {
+		state.confirmDialog = {
 			type:'submit',
 			content:'是否提交当前任务?',
 			fileUrls:[],
 			targetFileIds:[]
 		};
-		popupDelDialogRef.value.OpenDialog();
+		popupConfirmDialogRef.value.OpenDialog();
 	}
 	//重新提交
 	const UpdateTaskTargetReset = () => {
-		state.delDialog = {
+		state.confirmDialog = {
 			type:'submit',
 			content:'是否重新编辑当前任务?',
 			fileUrls:[],
 			targetFileIds:[]
 		};
-		popupDelDialogRef.value.OpenDialog();
+		popupConfirmDialogRef.value.OpenDialog();
 	}
 	//确定删除 确定提交
-	const DialogDelConfirm = () => {
-		if(state.delDialog.type == 'del'){//单个删除 批量删除
+	const DialogConfirm = () => {
+		if(state.confirmDialog.type == 'del'){//单个删除 批量删除
 			DelFileList();
-		}else if(state.delDialog.type == 'submit') {//提交
+		}else if(state.confirmDialog.type == 'submit') {//提交
 			submitTaskTarget();
 		}
 	}
 	const DelFileList = async() => {
-		const res = await DeleteFileList({ fileUrls: state.delDialog.fileUrls })
+		const res = await DeleteFileList({ fileUrls: state.confirmDialog.fileUrls })
 		if (res.code !== 200) {
 			uni.showToast({
 				title: res.msg,
@@ -434,14 +442,14 @@
 		}
 		const resData = await DelTaskTargetFileList({
 			targetId: state.targetId,
-			targetFileIds: state.delDialog.targetFileIds
+			targetFileIds: state.confirmDialog.targetFileIds
 		})
 		if (resData.code === 200) {
 			uni.showToast({
 				title: '删除成功!',
 				icon: 'none'
 			});
-			GetTaskTargetFileList();
+			GetTaskTargetFileList(false,'del');
 		}
 	}
 	//提交
@@ -452,10 +460,45 @@
 					title: '提交成功!',
 					icon: 'none'
 				});
-				GetTaskTargetFileList();
+				GetTaskTargetFileList(false,'submit');
 			}
 		})
 	}
+	//对比审核状态是否发生变化同时更新缓存数据
+	const updateCacheData = (type) => {
+		const targetStatus = state?.targetFileList?.targetStatus;
+		let taskTargetList = state?.details?.taskTargetVos || [];
+		if (state.auditStatus !== targetStatus) {
+			// 状态变化,删除目标项
+			taskTargetList.forEach(item=>{
+				if(item.id == state.targetId){
+					item.isShow = 1;//删除状态
+				}
+			})
+		} else {
+			// 状态未变且非提交(上传或删除)操作,更新文件列表
+			if (type !== 'submit'){
+				const targetItem = taskTargetList.find(item => item.id === state.targetId);
+				if (targetItem) {
+				    targetItem.taskTargetFileVos = state?.targetFileList?.taskTargetFileVos || [];
+					targetItem.fileNum = targetItem.taskTargetFileVos.length;
+				}
+			}else{
+				taskTargetList.forEach(item=>{
+					if(item.id == state.targetId){
+						item.isShow = 0;//显示
+					}
+				})
+			}
+			
+		}
+		// 关键:将结果写回 state
+		if (state?.details) {
+			state.details.taskTargetVos = taskTargetList;
+			uni.setStorageSync('submitMaterialDetailInfo',state.details);
+			uni.setStorageSync('isLoadSubmitMaterialTaskDetail',true);//返回是否重新更新任务详情数据
+		}
+	}
 	//返回
 	const GoBack = () => {
 		uni.navigateBack({
@@ -465,12 +508,14 @@
 </script>
 
 <style scoped lang="scss">
+	.page_body{
+		height: 100%;
+	}
 	.page_content_height{
 		display: flex;
 		flex-direction: column;
 		width: 100%;
-		// height: calc(100% - 326rpx);
-		flex:1;
+		height: calc(100% - 240rpx);
 		overflow: auto;
 	}
 	.page_content {
@@ -756,10 +801,12 @@
 	.page_foot{
 		position: fixed;
 		display: flex;
+		align-items: center;
 		left: 0;
 		right: 0;
 		bottom: 0;
-		padding: 20rpx 24rpx;
+		padding: 0 24rpx;
+		height: 130rpx;
 		background-color: #FFFFFF;
 		gap: 32rpx;
 		.del{

+ 44 - 16
pages/materialCollection/submitMaterial/taskDetail.vue

@@ -35,23 +35,25 @@
 		<view class="page_content">
 			<view class="total">
 				<view class="status_tag" :class="state.auditStatus">
-					<text>{{ tabStatusClassMap[state.auditStatus] }}:{{ state?.details?.taskTargetVos?.length || 0 }}</text>
+					<text>{{ tabStatusClassMap[state.auditStatus] }}:{{ state?.details?.taskTargetNum }}</text>
 				</view>
 			</view>
-			<view class="list_item" v-for="item in (state?.details?.taskTargetVos || [])" :Key="item.id">
-				<view class="item_name_file">
-					<view class="name_file">
-						<text class="name">{{item.targetName}}</text>
-						<text class="file_num">文件数量:{{item?.fileNum || 0}}</text>
+			<template v-for="item in (state?.details?.taskTargetVos || [])">
+				<view class="list_item" v-if="item.isShow!==1" :Key="item.id">
+					<view class="item_name_file">
+						<view class="name_file">
+							<text class="name">{{item.targetName}}</text>
+							<text class="file_num">文件数量:{{item?.fileNum || 0}}</text>
+						</view>
+						<view class="btn" @click="HandleDetail(item.id)">{{state.auditStatus == 'notSubmitList'?'立即提交':'查看'}}</view>
+					</view>
+					<view class="item_info">
+						<template v-for="text in ['departmentName','departmentGroupName','subjectName','gradeName','classTypeName','className','updateTime']">
+							<text class="info_text" v-if="item?.[text]" :key="text">{{item?.[text]}}</text>
+						</template>
 					</view>
-					<view class="btn" @click="HandleDetail(item.id)">{{state.auditStatus == 'notSubmitList'?'立即提交':'查看'}}</view>
-				</view>
-				<view class="item_info">
-					<template v-for="text in ['departmentName','departmentGroupName','subjectName','gradeName','classTypeName','className','updateTime']">
-						<text class="info_text" v-if="item?.[text]" :key="text">{{item?.[text]}}</text>
-					</template>
 				</view>
-			</view>
+			</template>
 		</view>
 	</view>
 </template>
@@ -60,7 +62,7 @@
 	import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
 	import navBar from '@/components/navBar.vue';
 	import { remainingDays } from '@/common/common.js';
-	import {onLoad} from '@dcloudio/uni-app';
+	import {onLoad,onShow} from '@dcloudio/uni-app';
 	import {
 		reactive,
 		ref,
@@ -90,14 +92,28 @@
 		'reviewReasonList':'已驳回',// 已驳回
 		'reviewList':'已提交'// 已提交
 	};
+	onShow(()=>{
+		const isLoadSubmitMaterialTaskDetail = uni.getStorageSync('isLoadSubmitMaterialTaskDetail');
+		if(isLoadSubmitMaterialTaskDetail){
+			OnLoadData();
+		}
+	})
+	onUnmounted(()=>{
+		uni.removeStorageSync('isLoadSubmitMaterialTaskDetail');
+	})
 	onLoad((option) => {
 		state.taskId = option.taskId;
 		state.auditStatus = option.auditStatus;
 	})
 	onMounted(() => {
-		state.details = uni.getStorageSync('submitMaterialDetailInfo') || {};
+		OnLoadData();
 		checkTextOverflow();
 	});
+	const OnLoadData = () => {
+		state.details = uni.getStorageSync('submitMaterialDetailInfo') || {};
+		const taskTargetData = state?.details?.taskTargetVos || [];
+		state.details.taskTargetNum = taskTargetData.filter(item=>item.isShow!=1)?.length;
+	}
 	const checkTextOverflow = () => {
 		nextTick(() => {
 			const instance = getCurrentInstance();
@@ -146,8 +162,20 @@
 	}
 	//提交材料
 	const HandleDetail = (targetId) => {
+		let auditStatus = '';
+		if(state.auditStatus == 'notSubmitList'){
+			auditStatus = '1';
+		}else if(state.auditStatus == 'notReviewList'){
+			auditStatus = '2';
+		}else if(state.auditStatus == 'reviewReasonList'){
+			auditStatus = '3';
+		}else if(state.auditStatus == 'reviewList'){
+			auditStatus = '4';
+		}else{
+			auditStatus = '';
+		}
 		uni.navigateTo({
-			url: `/pages/materialCollection/submitMaterial/submitDetail?taskId=${state.taskId}&targetId=${targetId}`
+			url: `/pages/materialCollection/submitMaterial/submitDetail?taskId=${state.taskId}&targetId=${targetId}&auditStatus=${auditStatus}`
 		});
 	}
 	//返回

+ 178 - 0
pages/materialCollection/taskOverview/personList.vue

@@ -0,0 +1,178 @@
+<template>
+	<view class="page_person_list">
+		<CommonHeader :title="headerTitle" @back="goBack"></CommonHeader>
+
+		<SearchBar v-model="searchWord" @search="handleSearch" :isFixed="true" :top="searchBarTop + 'rpx'" :border="false"></SearchBar>
+
+		<scroll-view scroll-y class="person_list" :style="{ paddingTop: contentPaddingTop + 'rpx' }">
+			<view v-for="(person, index) in filteredList" :key="person.userId || person.id || index" class="person_item">
+				<view class="person_info">
+					<text class="person_name">{{ person.thirdName || person.name }}</text>
+					<text class="person_code">({{ person.thirdCode || person.userAccount || '' }})</text>
+				</view>
+				<view class="person_action" @click="openDeleteModal(index)">
+					<text class="delete_text">删除</text>
+				</view>
+			</view>
+
+			<view v-if="filteredList.length === 0" class="empty_state">
+				<text class="empty_text">暂无人员</text>
+			</view>
+		</scroll-view>
+
+		<ConfirmModal
+			:visible="showDeleteModal"
+			title="提示"
+			:content="`确定要删除【${deletePersonName}】吗?`"
+			cancelText="取消"
+			confirmText="确定"
+			@cancel="closeDeleteModal"
+			@confirm="confirmDelete"
+		></ConfirmModal>
+	</view>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from 'vue';
+import CommonHeader from '@/components/commonHeader.vue';
+import SearchBar from '@/components/searchBar.vue';
+import ConfirmModal from '@/components/confirmModal.vue';
+import { useSafeArea } from '@/common/safeArea';
+
+const { statusBarHeight, initSafeArea } = useSafeArea();
+
+const HEADER_CONTENT_HEIGHT = 174;
+const SEARCHBAR_HEIGHT = 60;
+const SPACING = 24;
+
+const searchBarTop = computed(() => statusBarHeight.value + HEADER_CONTENT_HEIGHT);
+const contentPaddingTop = computed(() => statusBarHeight.value + HEADER_CONTENT_HEIGHT + SEARCHBAR_HEIGHT + SPACING);
+
+const searchWord = ref('');
+
+const personList = ref([]);
+const objectTypeLabel = ref('');
+
+const showDeleteModal = ref(false);
+const deleteIndex = ref(-1);
+const deletePersonName = ref('');
+
+const filteredList = computed(() => {
+	if (!searchWord.value) return personList.value;
+	const keyword = searchWord.value.toLowerCase();
+	return personList.value.filter(person => {
+		const name = (person.thirdName || person.name || '').toLowerCase();
+		const code = (person.thirdCode || person.userAccount || '').toLowerCase();
+		return name.includes(keyword) || code.includes(keyword);
+	});
+});
+
+const headerTitle = computed(() => {
+	return `${objectTypeLabel.value || ''} 已选${personList.value.length}人`;
+});
+
+const handleSearch = (keyword) => {
+	searchWord.value = keyword;
+};
+
+const openDeleteModal = (index) => {
+	const person = personList.value[index];
+	deletePersonName.value = person.thirdName || person.name || '';
+	deleteIndex.value = index;
+	showDeleteModal.value = true;
+};
+
+const closeDeleteModal = () => {
+	showDeleteModal.value = false;
+	deleteIndex.value = -1;
+	deletePersonName.value = '';
+};
+
+const confirmDelete = () => {
+	if (deleteIndex.value >= 0) {
+		personList.value.splice(deleteIndex.value, 1);
+	}
+	closeDeleteModal();
+};
+
+const goBack = () => {
+	uni.setStorageSync('personListResult', JSON.stringify({
+		users: personList.value
+	}));
+	uni.navigateBack();
+};
+
+onMounted(() => {
+	initSafeArea();
+
+	const data = uni.getStorageSync('personListData');
+	if (data) {
+		try {
+			const parsed = JSON.parse(data);
+			// 不去重,直接使用所有用户
+			personList.value = parsed.users || [];
+			objectTypeLabel.value = parsed.tab || '';
+		} catch (e) {
+			console.error('解析人员列表数据失败:', e);
+		}
+	}
+});
+</script>
+
+<style lang="scss">
+.page_person_list {
+	display: flex;
+	flex-direction: column;
+	min-height: 100vh;
+}
+
+.person_list {
+	flex: 1;
+	padding-left: 24rpx;
+	padding-right: 24rpx;
+	padding-bottom: 24rpx;
+	box-sizing: border-box;
+}
+
+.person_item {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	height: 86rpx;
+	border-bottom: 2rpx solid #F3F3F3;
+	.person_info {
+		display: flex;
+		align-items: center;
+
+		.person_name {
+			font-size: 28rpx;
+			color: #666;
+		}
+
+		.person_code {
+			font-size: 28rpx;
+			color: #666;
+			margin-left: 16rpx;
+		}
+	}
+
+	.person_action {
+		.delete_text {
+			font-size: 28rpx;
+			color: #F56C6C;
+		}
+	}
+}
+
+.empty_state {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	padding: 100rpx 0;
+
+	.empty_text {
+		font-size: 28rpx;
+		color: #999999;
+	}
+}
+</style>

+ 674 - 0
pages/materialCollection/taskOverview/selectObjectNoDedup.vue

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

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

@@ -127,7 +127,7 @@
 		audioHonorData(params).then(res=>{
 			if(res.code == 200){
 				uni.showToast({
-					title: '审核通过!',
+					title: status == 2?'驳回成功!':'审核通过!',
 					icon: 'none'
 				})
 				uni.setStorageSync('isLoadHonorAuditList', true);//刷新荣誉审核列表

+ 1 - 1
pages/teacherHonor/myHonor/index.vue

@@ -156,7 +156,7 @@
 		OnLoadData(true);
 	});
 	onUnmounted(()=>{
-		uni.setStorageSync('isLoadHonorOverview', false);
+		uni.setStorageSync('isLoadMyHonorList', false);
 	})
 	//查询荣誉类型列表
 	const GetHonorTypeList = () => {

+ 217 - 14
pages/teacherHonor/myHonor/uploadEditMyHonor.vue

@@ -30,6 +30,38 @@
 					</uv-upload>
 				</uni-forms-item>
 				<uni-forms-item label="佐证材料:">
+					<template v-if="state.type=='view'">
+						<view class="upload_file_list_item" v-for="item in state.formData.docDatas" :key="item.createdAt">
+							<image class="list_item_icon" src="/static/image/icon/file.png"></image>
+							<view class="list_item_content">
+								<view class="item_content_title">{{item.documentName}}</view>
+								<view class="item_content_info">
+									<view class="size">{{item.fileSize}}</view>
+									<view class="time">{{item.createdAt}}</view>
+								</view>
+							</view>
+							<view class="list_item_preview" @click="PreviewFile(item)">预览</view>
+						</view>
+					</template>
+					<template v-else>
+						<!-- maxSize:单文件上限 MB;0 表示不限制 maxCount:列表最多文件数 -->
+						<kex-file-uploader ref="fileUploader" mode="headless" :max-count="20" :maxSize="100"></kex-file-uploader>
+						<view class="upload_file_btn" @click="ChooseUploadFile">
+							<uni-icons class="upload_file_btn_icon" type="plusempty"></uni-icons>
+							<view class="upload_file_btn_text">上传佐证材料</view>
+						</view>
+						<view class="upload_file_list_item" v-for="item in state.formData.docDatas" :key="item.createdAt" @click="PreviewFile(item)">
+							<image class="list_item_icon" src="/static/image/icon/file.png"></image>
+							<view class="list_item_content">
+								<view class="item_content_title">{{item.documentName}}</view>
+								<view class="item_content_info">
+									<view class="size">{{item.fileSize}}</view>
+									<view class="time">{{item.createdAt}}</view>
+								</view>
+							</view>
+							<uni-icons class="list_item_close" type="close" @click.stop="state.formData.docDatas.splice(i, 1)"></uni-icons>
+						</view>
+					</template>
 				</uni-forms-item>
 				<uni-forms-item label="驳回原因 :" v-if="state.formData.overruleContent">
 					{{state.formData.overruleContent}}
@@ -41,6 +73,10 @@
 		</view>
 		<view class="page_foot" v-if="state.type!='view'"><button class="btn_submit" type="primary" :loading="state.loading" @click="honorTypeConfirm">确认</button></view>
 	</view>
+	<!-- 提示框 -->
+	<popupPreviewFile ref="popupDialogRef" :filePath="state.previewPopup.filePath"></popupPreviewFile>
+	<!-- 文件、图片下载 -->
+	<ss-download ref="ssdownload"></ss-download>
 </template>
 
 <script setup>
@@ -53,6 +89,8 @@
 	import uniDateformat from '@/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue';
 	import uvUpload from '@/uni_modules/uv-upload/components/uv-upload/uv-upload.vue';
 	import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue';
+	import ssDownload from '@/uni_modules/ss-download/components/ss-download/ss-download.vue';
+	import popupPreviewFile from '@/components/popupPreviewFile.vue';
 	import {queryHonorTypeDictList,queryHonorDataDetailById,addHonorCertData,updateHonorCertData} from '@/reqApi/teacherHonor.js';
 	import { unioformDateTransform,fileSizeConvert } from '@/common/common.js';
 	import config from '@/config.js'; // 引入配置文件
@@ -77,16 +115,26 @@
 		honorTypeData:[],//荣誉类型下拉
 		dynamicFormData:[],//动态表单
 		dictDatas:[],//动态表单传参
-		loading:false
+		loading:false,
+		previewPopup:{
+			filePath:''
+		}
 	})
 	const todayStr = ref(new Date().toISOString().split('T')[0]);
 	const rules = ref({
 		honorTypeValue: { rules: [{ required: true, errorMessage: '请选择荣誉类型' }] },
 		certPicDatas: { rules: [{ required: true, errorMessage: '请上传荣誉证书' }] },
 	});
+	const fileUploader = ref(null);
+	const popupDialogRef = ref(null);
+	const ssdownload = ref(null);
+	const token = ref(uni.getStorageSync('token'));
+	const apiBaseUrl = ref('');
 	onLoad(async(option) => {
 		state.id = option.id;
 		state.type = option.type;
+		getApiBaseUrl();
+		uni.setStorageSync('isLoadMyHonorList', false);//返回列表页是否重新加载我的荣誉列表
 		await GetHonorTypeDictList(option.type);//查询荣誉类型下拉数据
 		if(option.type == 'upload'){
 			state.title = '上传荣誉';
@@ -98,8 +146,16 @@
 			}
 			GetHonorDataDetailById();
 		}
-		uni.setStorageSync('isLoadMyHonorList', false);//返回列表页是否重新加载我的荣誉列表
 	})
+	//上传接口地址
+	const getApiBaseUrl = () => {
+		if (process.env.NODE_ENV === 'development') {//本地开发环境
+		  const SYSTEM_INFO = uni.getSystemInfoSync();//获取系统信息的同步接口
+		  apiBaseUrl.value = SYSTEM_INFO.uniPlatform === 'web' ? config.proxyBaseUrl:config.apiBaseUrl;//读取配置文件的apiBaseUrl变量
+		} else {//生产/测试环境
+		  apiBaseUrl.value = config.apiBaseUrl
+		}
+	}
 	//查询荣誉类型下拉数据
 	const GetHonorTypeDictList = async (type) => {
 		await queryHonorTypeDictList().then(res=>{
@@ -268,8 +324,6 @@
 					})
 					uni.setStorageSync('isLoadMyHonorList', true);//返回列表页是否重新加载我的荣誉列表
 					GoBack();
-				}else{
-					
 				}
 			}).finally(()=>{
 				state.loading = false;
@@ -311,20 +365,12 @@
 	}
 	const uploadFilePromise = (url) => {
 		return new Promise((resolve, reject) => {
-			const token = uni.getStorageSync('token'); // 假设从本地存储获取token
-			let apiBaseUrl = '';
-			if (process.env.NODE_ENV === 'development') {//本地开发环境
-			  const SYSTEM_INFO = uni.getSystemInfoSync();//获取系统信息的同步接口
-			  apiBaseUrl = SYSTEM_INFO.uniPlatform === 'web' ? config.proxyBaseUrl:config.apiBaseUrl;//读取配置文件的apiBaseUrl变量
-			} else {//生产/测试环境
-			  apiBaseUrl = config.apiBaseUrl
-			}
 			let a = uni.uploadFile({
-				url: `${apiBaseUrl}/api/v1/teach/oss/file/oss/upload_filesSele`,
+				url: `${apiBaseUrl.value}/api/v1/teach/oss/file/oss/upload_filesSele`,
 				filePath: url,
 				name: 'file',
 				header:{
-					Authorization:token
+					Authorization:token.value
 				},
 				success: (res) => {
 					const resdata = JSON.parse(res.data);
@@ -333,6 +379,74 @@
 			});
 		})
 	}
+	//上传 图片 视频 文档
+	const ChooseUploadFile = () => {
+		fileUploader.value.chooseFile({//选择上传文件
+			count: 1,
+			success: (files) => {
+				fileUploader.value.upload({//上传单个文件
+					url:`${apiBaseUrl.value}/api/v1/teach/oss/file/oss/upload_filesSele`,
+					file: files[0],
+					name: 'file',
+					header: {Authorization: token.value},
+					method: 'POST',
+					withCredentials: true, // iOS 本地测远程且要带 cookie
+					success: (res) => {
+						const result = JSON.parse(res.result);
+						state.formData.docDatas.push({
+							documentName:result.data.fileName,
+							documentUrl:result.data.url,
+							fileSize:fileSizeConvert(files?.[0]?.size || 0),
+							createdAt:unioformDateTransform(new Date())
+						})
+					}
+				});
+			}
+		})
+	}
+	//预览
+	const PreviewFile = (item) => {
+		const fileType = item?.documentName?.split('.')?.[1] || '';
+		if(IsImageExts(fileType)){//图片预览
+			state.previewPopup.filePath = item.documentUrl;
+			popupDialogRef.value.OpenDialog();
+		}else{//文件预览
+			ToDownloadFile(item)
+		}
+	}
+	//判断是否是图片
+	const IsImageExts = (fileType) => {
+		const type = fileType?.toLowerCase();
+		const imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp','svg', 'tiff', 'tif', 'ico', 'avif', 'heic', 'heif'];
+		return imageExts.includes(type)
+	}
+	//判断是不是视频
+	const IsVideoExts = (fileType) => {
+		const type = fileType?.toLowerCase();
+		const videoExts = [
+		    'mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv', 
+		    'webm', 'm4v', '3gp', 'mpeg', 'mpg', 'mts', 
+		    'm2ts', 'ts', 'vob', 'ogv', 'ogg', 'rm', 'rmvb'
+		];
+		return videoExts.includes(type)
+	}
+	//下载
+	const ToDownloadFile = (item) => {
+		const fileType = item?.documentName?.split('.')?.[1] || '';
+		let type = '';
+		if(IsImageExts(fileType)){
+			type = '1';//1:图片 2 文档 3 视频
+		}else if(IsVideoExts(fileType)){
+			type = '3';
+		}else{
+			type = '2';
+		}
+		ssdownload?.value?.toDownload({
+			type:fileType,
+			src:item.documentUrl,
+			fileName:item.documentName
+		});
+	}
 	const GoBack = () => {
 		uni.navigateBack({
 			delta: 1
@@ -427,6 +541,95 @@
 					}
 				}
 			}
+			.upload_file_btn{
+				width: 100%;
+				height: 120rpx;
+				display: flex;
+				justify-content: center;
+				flex-direction: column;
+				align-items: center;
+				background-color: #FAFBFF;
+				border-radius: 20rpx;
+				border: 2rpx dashed #CCCED4;
+				.upload_file_btn_icon{
+					font-size: 40rpx !important;
+					color: #CCCED4 !important;
+				}
+				.upload_file_btn_text{
+					font-weight: 400;
+					font-size: 24rpx;
+					color: #CCCED4;
+					margin-top: 8rpx;
+				}
+			}
+			.upload_file_list_item{
+				display: flex;
+				align-items: center;
+				width: 100%;
+				min-height: 120rpx;
+				padding: 20rpx 24rpx;
+				background-color: #FFFFFF;
+				border-radius: 20rpx;
+				border: 2rpx solid #EBEEF5;
+				box-sizing: border-box;
+				margin-top: 24rpx;
+
+				.list_item_icon {
+					width: 80rpx;
+					height: 80rpx;
+					margin-right: 20rpx;
+					flex-shrink: 0;
+				}
+
+				.list_item_content {
+					flex: 1;
+					// width: 0;
+					// overflow: hidden;
+
+					.item_content_title {
+						width: 100%;
+						font-weight: 500;
+						font-size: 28rpx;
+						color: #333333;
+						word-break: break-all;
+						// white-space: nowrap;
+						// overflow: hidden;
+						// text-overflow: ellipsis;
+						// word-break: keep-all; /* ✅ 防止意外换行 */
+					}
+
+					.item_content_info {
+						display: flex;
+						flex-wrap: wrap;
+						align-items: center;
+						gap: 4rpx 20rpx;
+						margin-top: 8rpx;
+
+						.size {
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #999999;
+							flex-shrink: 0;
+						}
+						.time {
+							font-size: 24rpx;
+							color: #999999;
+							flex-shrink: 0;
+						}
+					}
+				}
+				.list_item_close {
+					flex-shrink: 0;
+					color: #999999 !important;
+					font-size: 48rpx !important;
+				}
+				.list_item_preview{
+					flex-shrink: 0;
+					font-weight: 400;
+					font-size: 28rpx;
+					color: #2E64FA;
+				}
+			}
 		}
 	}
 	.page_foot{

+ 8 - 0
reqApi/notification.js

@@ -79,4 +79,12 @@ export const updateTaskTarget = (taskTargetId) => {
 // 具体采集任务保存上传的文件地址
 export const uploadTaskTargetFileList = (data) => {
   return request.post('/api/v1/teaching_plan/collect/task_target_file/upload_task_target_file_list',data)
+}
+// 待审核的通过和驳回
+export const updateReviewStatus = (data) => {
+  return request.post('/api/v1/teaching_plan/collect/task_target_review/update_review_status',data)
+}
+// 已审核的通过和驳回
+export const ChangeReviewStatus = (data) => {
+  return request.post('/api/v1/teaching_plan/collect/task_target_review/change_review_status',data)
 }

+ 0 - 3
reqApi/teacherHonor.js

@@ -66,7 +66,4 @@ export function queryHonorTeacherDetail(id) {//查询荣誉教师单个荣誉证
 }
 export function deleteHonorData(id) {//删除荣誉证书接口
 	return request.get(`/api/v1/deleteHonorData/${id}`)
-}
-export function uploadFilesSele(data) {//文件上传
-	return request.post('/api/v1/teach/oss/file/oss/upload_filesSele',data)
 }

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


+ 7 - 3
style/common.scss

@@ -554,9 +554,11 @@ uni-page-body {
 	.tab_item {
 		flex:1;
 		min-width: 128rpx;
-		display: inline-flex;
-		justify-content: center;
-		align-items: center;
+		// display: inline-flex;
+		// justify-content: center;
+		// align-items: center;
+		line-height: 68rpx;
+		text-align: center;
 		font-weight: 400;
 		font-size: 28rpx;
 		color: #333333;
@@ -566,6 +568,8 @@ uni-page-body {
 		border-radius: 8rpx;
 		border: 2rpx solid #DCDFE6;
 		white-space: nowrap;
+		overflow: hidden;
+		text-overflow: ellipsis;
 		&.selected {
 			font-weight: 500;
 			color: #2E64FA;