SanHQin 1 năm trước cách đây
mục cha
commit
2a04853346

+ 3 - 1
src/App.vue

@@ -881,10 +881,12 @@ hr {
   margin-top: 20px;
   position: relative;
   width: 99%;
+	padding-right: 250px;
+	box-sizing: border-box;
   .manageSelects {
     display: flex;
     flex-wrap: wrap;
-    width: 80%;
+    width: 100%;
     .selectsBlock {
       display: flex;
       margin-right: 30px;

+ 4 - 0
src/components/tool/getProjectNo.js

@@ -3,6 +3,9 @@ import store from '@/config/config' //vuex
 
 const TYPE_NO = {
     "XM":"/getProjectNo",
+		"CX":"/getProjectNo",
+		"CY":"/getProjectNo",
+		"SJ":"/getProjectNo",
     "HD":"/getActivityNo",
     'ZJ':"/getFundNo",
 }
@@ -11,6 +14,7 @@ export default function getProjectNo(str="XM"){
     return new Promise((resolve,reject)=>{
         ajax.get(store.state.api+TYPE_NO[str],{
             uid:store.state.userInfo.userid,
+						type:str
         }).then(res=>{
             console.log(res['data'])
             if(res['data'][0].length==0||res['data'][0][0]['No']==null)return resolve(`${str}0000001`)

+ 0 - 1
src/components/tool/getWord2.js

@@ -28,7 +28,6 @@ function getWord2(val){
 			let ImageList = await getImage(val.elementList);
 
 			// resolve()
-			console.log(ImageList)
 			let zip=new PizZip(content);
 
 			// 图片处理

+ 3 - 1
src/permission.js

@@ -50,8 +50,10 @@ function getSystemState(to, callback) {
 
 router.beforeEach(async(to, from, next) => {
     try {
+				
 				/*本地环境👇*/
-				// uid = "1270";
+				// let userId = to.query["userid"] || "201901766"
+				// uid = userId;//管理员
 				// setToken(btoa(md5(uid)));
 				// userLogin((isLogin) => {
 				// 	getSystemState(to, () => {

+ 3 - 3
src/views/commission/commission.vue

@@ -112,10 +112,10 @@
           </el-select>
         </div>
       </div>
-      <!-- <div class="ProjectManagementQuery">
-          <el-input v-model="input" style="width:240px" placeholder="请输入项目名称/编号"></el-input>
+      <div class="ProjectManagementQuery">
+          <el-input v-model="input" style="width:200px" placeholder="请输入项目名称/编号"></el-input>
           <el-button type="primary" class="btn" @click="getData" size="mini">查询</el-button>
-        </div> -->
+        </div>
     </div>
     <!-- 搜索栏结束 -->
 

+ 19 - 12
src/views/commission/components/projectBook.vue

@@ -140,7 +140,7 @@
       <tr v-if="bookData.isupload==5 || qpList.filter(i=>i.type==4).length>0">
         <td colspan="8">
 					<div class="defaultHeight">
-						<p class="bold">所在学院部门审核意见:<el-button  v-if="!isQpButton && $store.state.userInfo.type==4" type="primary" size="small" @click="openQp">签批</el-button></p>
+						<p class="bold">所在学院部门审核意见:<el-button  v-if="!isQpButton && $store.state.userInfo.type==4 && showBtn" type="primary" size="small" @click="openQp">签批</el-button></p>
           	<div v-for="(item, index) in qpList.filter(i=>i.type==4)" :key="index" class="qpItem">
           	  <div>{{ item.text }}</div>
           	  <div>{{ item.bm }} {{ item.username }} {{ item.time }}</div>
@@ -152,7 +152,7 @@
 			<tr v-if="bookData.isupload==6 || qpList.filter(i=>i.type==0).length>0">
         <td colspan="8">
 					<div class="defaultHeight">
-          	<p class="bold">创新创业学院审核意见:<el-button  v-if="!isQpButton && $store.state.userInfo.type==0" type="primary" size="small" @click="openQp">签批</el-button></p>
+          	<p class="bold">创新创业学院审核意见:<el-button  v-if="!isQpButton && $store.state.userInfo.type==0 && showBtn" type="primary" size="small" @click="openQp">签批</el-button></p>
           	<div v-for="(item, index) in qpList.filter(i=>i.type==0)" :key="index" class="qpItem">
           	  <div>{{ item.text }}</div>
           	  <div>{{ item.bm }} {{ item.username }} {{ item.time }}</div>
@@ -163,7 +163,7 @@
 			<tr v-if="bookData.isupload==7 || qpList.filter(i=>i.type==3).length>0">
         <td colspan="8">
 					<div class="defaultHeight">
-          	<p class="bold">学校终审意见:<el-button  v-if="!isQpButton && $store.state.userInfo.type==3" type="primary" size="small" @click="openQp">签批</el-button></p>
+          	<p class="bold">学校终审意见:<el-button  v-if="!isQpButton && $store.state.userInfo.type==3 && showBtn" type="primary" size="small" @click="openQp">签批</el-button></p>
           	<div v-for="(item, index) in qpList.filter(i=>i.type==3)" :key="index" class="qpItem">
           	  <div>{{ item.text }}</div>
           	  <div>{{ item.bm }} {{ item.username }} {{ item.time }}</div>
@@ -342,7 +342,7 @@ export default {
       ttt: "",
       bookData: {},
 			loading:false,
-      dialogVisible: true,
+      dialogVisible: false,
       ttype: 0,
       phType: 0,
       qpMessage: "",
@@ -357,14 +357,12 @@ export default {
 				// {tit:"专家意见",key:'5'},
 				{tit:"创新创业学院审核",key:'0'},
 				{tit:"所在学院/部门审核",key:'4'},
-			]
-			// typeListStatus:{
-			// 	"5":"评审委员会意见",
-			// 	"4":"所在学院部门",
-			// 	"3":"所在学院领导审核",
-			// 	"0":"创新创业综合审核-初审",
-			// }
-
+			],
+			typeListStatusNoShowBtn:{
+				'0':[6,7],
+				'3':[7],
+				'4':[5,6],
+			}
     };
   },
   methods: {
@@ -414,6 +412,7 @@ export default {
             this.phList = data[0];
           }
 					this.phList = [...defaultList,...this.phList]
+					this.loading = false;
         },
         (err) => {
           console.log(err);
@@ -522,10 +521,13 @@ export default {
             res.data[0].length > 0
               ? Math.max(...res.data[0].map((obj) => obj.type))
               : -1;
+
+
           this.isAgree =
             res.data[0].length > 0
               ? Math.max(...res.data[0].map((obj) => obj.isAgree))
               : 0;
+
           for (var i = 0; i < res.data[0].length; i++) {
             if (
               res.data[0][i].userid == this.$store.state.userInfo.userid &&
@@ -674,6 +676,11 @@ export default {
       );
     },
   },
+	computed:{
+	  showBtn(){
+			return this.typeListStatusNoShowBtn[this.$store.state.userInfo.type].includes(this.bookData['isupload']);
+		}
+	},
 
   mounted() {
     this.getData();

+ 411 - 20
src/views/commission/components/projectLookstudnt.vue

@@ -43,10 +43,10 @@
           </tr> -->
           <tr id="schoolRadio" class="checkArea">
             <td colspan="2" ref="schoolRadio">美丽校园改造项目(特色项目)</td> <td colspan="5">
-              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].indexOf('1')!=-1?'☑ ':'□ '"></span><span>校园安全项目</span></span>
-              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].indexOf('2')!=-1?'☑ ':'□ '"></span><span>环境治理项目</span></span>
-              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].indexOf('3')!=-1?'☑ ':'□ '"></span><span>校园服务项目</span></span>
-              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].indexOf('4')!=-1?'☑ ':'□ '"></span><span>文创装置项目</span></span>
+              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].includes('1')?'☑ ':'□ '"></span><span>校园安全项目</span></span>
+              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].includes('2')?'☑ ':'□ '"></span><span>环境治理项目</span></span>
+              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].includes('3')?'☑ ':'□ '"></span><span>校园服务项目</span></span>
+              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].includes('4')?'☑ ':'□ '"></span><span>文创装置项目</span></span>
             </td>
           </tr>
 					<tr id="schoolRadio">
@@ -54,19 +54,19 @@
 							<span class="jc">优先支持项目</span><br><span>(可多选)</span>
 						</td> <td colspan="5" style="padding: 20px 0;">
 							<div style="display: flex;flex-direction: column;align-items: flex-start;padding-left:20px ;">
-								<span class="checkAreaBlc"><span v-text="downWordData['checkList'].indexOf('1')!=-1?'☑ ':'□ '"></span><span>团队合作项目、跨学科合作项目。</span></span>
-              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].indexOf('2')!=-1?'☑ ':'□ '"></span><span>科技创新、低空经济、银发经济、乡村振兴、助残助学、非遗文创等新技术、新产业、新业态、新模式方面的项目。</span></span>
-              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].indexOf('3')!=-1?'☑ ':'□ '"></span><span>企业真实生产经营项目或外包服务项目。</span></span>
-              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].indexOf('4')!=-1?'☑ ':'□ '"></span><span>社会征集项目、产业命题项目。</span></span>
-								<span class="checkAreaBlc"><span v-text="downWordData['checkList'].indexOf('5')!=-1?'☑ ':'□ '"></span><span>近两年内参与校级以上创新创业大赛并获奖的项目。</span></span>
-              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].indexOf('6')!=-1?'☑ ':'□ '"></span><span>美丽校园改造计划中的校园智能产品及文创产品的研发项目。</span></span>
-              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].indexOf('7')!=-1?'☑ ':'□ '"></span><span>企申报人为港澳籍、学校扶贫班及在校贫困生申报的项目</span></span>
+								<span class="checkAreaBlc"><span v-text="downWordData['checkList'].includes('1')?'☑ ':'□ '"></span><span>团队合作项目、跨学科合作项目。</span></span>
+              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].includes('2')?'☑ ':'□ '"></span><span>科技创新、低空经济、银发经济、乡村振兴、助残助学、非遗文创等新技术、新产业、新业态、新模式方面的项目。</span></span>
+              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].includes('3')?'☑ ':'□ '"></span><span>企业真实生产经营项目或外包服务项目。</span></span>
+              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].includes('4')?'☑ ':'□ '"></span><span>社会征集项目、产业命题项目。</span></span>
+								<span class="checkAreaBlc"><span v-text="downWordData['checkList'].includes('5')?'☑ ':'□ '"></span><span>近两年内参与校级以上创新创业大赛并获奖的项目。</span></span>
+              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].includes('6')?'☑ ':'□ '"></span><span>美丽校园改造计划中的校园智能产品及文创产品的研发项目。</span></span>
+              	<span class="checkAreaBlc"><span v-text="downWordData['checkList'].includes('7')?'☑ ':'□ '"></span><span>企申报人为港澳籍、学校扶贫班及在校贫困生申报的项目</span></span>
 							</div>
 							
-              <!-- <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].indexOf('1')!=-1?'☑ ':'□ '"></span><span>校园安全项目</span></span>
-              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].indexOf('2')!=-1?'☑ ':'□ '"></span><span>环境治理项目</span></span>
-              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].indexOf('3')!=-1?'☑ ':'□ '"></span><span>校园服务项目</span></span>
-              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].indexOf('4')!=-1?'☑ ':'□ '"></span><span>文创装置项目</span></span> -->
+              <!-- <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].includes('1')!=-1?'☑ ':'□ '"></span><span>校园安全项目</span></span>
+              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].includes('2')!=-1?'☑ ':'□ '"></span><span>环境治理项目</span></span>
+              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].includes('3')!=-1?'☑ ':'□ '"></span><span>校园服务项目</span></span>
+              <span class="checkAreaBlc"><span v-text="downWordData['schoolRadio'].includes('4')!=-1?'☑ ':'□ '"></span><span>文创装置项目</span></span> -->
             </td>
           </tr>
           <!-- <tr id="applyParsonRadio">
@@ -190,6 +190,36 @@
               <span v-html="downWordData.introduce.plan"></span>
             </td>
           </tr>
+					<tr>
+        <td class="bold">附件上传</td>
+      	  <td
+      	    colspan="6"
+      	    class="textLeft"
+      	    style="height: 200px; position: relative"
+      	  >
+      	    <!-- <el-button type="primary" style="position: absolute; right: 130px; top: 5px" v-if="![1,2].includes($store.state.userInfo.type) && wordData.courseId" @click="$emit('saveFile')">保存</el-button> -->
+      	    <div
+      	      v-if="downWordData.attachment"
+      	      :class="downWordData.attachment.length > 0 ? 'bigBlock' : 'noFileBox'"
+      	    >
+      	      <div
+      	        class="fileBlock"
+      	        v-for="(item, index) in downWordData.attachment"
+      	        :key="index + 'l'"
+      	      >
+      	        <div class="fileBox">
+      	          <div
+      	            class="fileBoxLeft"
+      	            @click="checkFile(item.url)"
+      	          >
+      	            <div class="chapter_upload_l_i3"></div>
+      	            <div class="titName">{{ item.fileName }}</div>
+      	          </div>
+      	        </div>
+      	      </div>
+      	    </div>
+      	  </td>
+      	</tr>
           <tr id="fund">
             <td rowspan="12" ref="fund">预算经费</td><td>总经费</td><td colspan="5" v-text="reversedMessage==0?'':reversedMessage"></td>
           </tr>
@@ -269,19 +299,181 @@
           </div>
         </table>
           <!-- <el-button style="margin-top:20px" type="primary" @click="work">下载表格</el-button> 下载word文档 -->
+				<!-- 展示文件 -->
+				<el-dialog
+				title="展示文件"
+				:visible.sync="showFile"
+				top="1vh"
+				width="80vw"
+				append-to-body
+				>
+				<div class="showFileArea" style="height: 80vh">
+				<!-- <vpdf v-if="/^\s*$/g.test(showFileUrl)&&showFileUrl.split('.')[showFileUrl.split('.').length-1]=='pdf'" :pdfUrl="showFileUrl"></vpdf> -->
+				<div
+					class="workd_media"
+					style="width: 90%; height: 90%"
+					v-if="videoDetail.sources"
+				>
+					<video-player
+						class="video-player vjs-custom-skin"
+						:playsinline="true"
+						:options="videoDetail"
+						@play="onPlayerPlay($event)"
+						style="width: 90%; height: 90%; margin: 0 auto"
+					></video-player>
+				</div>
+				<vword
+					style="width: 100%; height: 100%; overflow: auto"
+					class="fullStyle"
+					v-else-if="Wordss['type'] != 'pdf' && Wordss['name'] != '图片'"
+					:pdfUrl="
+						'https://view.officeapps.live.com/op/view.aspx?src=' + showFileUrl
+					"
+				></vword>
+				<vpdf
+					style="width: 100%; height: 100%; overflow: auto"
+					class="fullStyle"
+					:pdfUrl="showFileUrl"
+					v-else-if="Wordss['type'] == 'pdf'"
+				></vpdf>
+				<img
+					:src="showFileUrl"
+					alt="图片哦"
+					v-else-if="Wordss['name'] == '图片'"
+					style="width: auto; height: auto; max-width: 100%; max-height: 100%"
+				/>
+				</div>
+				<!-- <el-button type="primary" size="mini" @click="downFile(showFileUrl)">下载文件</el-button> -->
+				</el-dialog>
     </div>
     </template>
       
     <script>
       import {getWord} from '@/components/tool/getWord'
+			import vpdf from "@/components/vpdf.vue";
+			import vword from "@/components/vword.vue";
       export default {
+				components:{
+					vpdf,
+					vword
+				},
         data() {
           return {
               downWordData:{
-               
+								checkList:[],
+								schoolRadio:[],
+								beginTime:"",
+								endTime:"",
+								studentS:[],
+								teacherS:[],
+								introduce:{},
+								fund:{}
               },
-							loading:false
-              
+							loading:false,
+              word: [
+      				  "DOC",
+      				  "DOCX",
+      				  "DOCM",
+      				  "DOTM",
+      				  "DOTX",
+      				  "PPTX",
+      				  "PPSX",
+      				  "PPT",
+      				  "PPS",
+      				  "PPTM",
+      				  "POTM",
+      				  "PPAM",
+      				  "POTX",
+      				  "PPSM",
+      				  "XLSX",
+      				  "XLS",
+      				],
+      				pdf: ["PDF"],
+      				image: [
+      				  "BMP",
+      				  "PJP",
+      				  "APNG",
+      				  "PNG",
+      				  "JPG",
+      				  "GIF",
+      				  "SVG",
+      				  "JPEG",
+      				  "JPG",
+      				  "ICO",
+      				  "PGPEG",
+      				  "AVIF",
+      				],
+      				vedio: [
+      				  "AVI",
+      				  "NAVI",
+      				  "MPEG",
+      				  "ASF",
+      				  "MOV",
+      				  "WMV",
+      				  "3GP",
+      				  "RM",
+      				  "RMVB",
+      				  "FLV",
+      				  "F4V",
+      				  "H.264",
+      				  "H.265",
+      				  "REAL VIDEO",
+      				  "MKV",
+      				  "WebM",
+      				  "HDDVD",
+      				  "MP4",
+      				  "MPG",
+      				  "M4V",
+      				  "MGV",
+      				  "OGV",
+      				  "QTM",
+      				  "STR",
+      				  "AMC",
+      				  "DVX",
+      				  "EVO",
+      				  "DAT",
+      				  "OGG",
+      				  "OGM",
+      				],
+      				playerOptions: {
+      				  playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
+      				  autoplay: false, //如果true,浏览器准备好时开始回放。
+      				  muted: false, // 默认情况下将会消除任何音频。
+      				  loop: false, // 导致视频一结束就重新开始。
+      				  preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+      				  language: "zh-CN",
+      				  aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+      				  fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+      				  sources: [
+      				    {
+      				      type: "video/mp4", //这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目   || "video/ogg"|| "video/webm"
+      				      src: "", //url地址require("../../assets/media/aaa.mp4")
+      				    },
+      				  ],
+      				  // poster: require("../../assets/tu31.png"), //你的封面地址
+      				  // poster: dataRes.imgUrl, //你的封面地址
+      				  notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
+      				  controlBar: {
+      				    timeDivider: true, //当前时间和持续时间的分隔符
+      				    durationDisplay: true, //显示持续时间
+      				    remainingTimeDisplay: false, //是否显示剩余时间功能
+      				    fullscreenToggle: true, //全屏按钮
+      				  },
+      				},
+      				playerO: {},
+      				videoDetail: {},
+							Wordss:{},
+							showFileUrl:"",
+							showFile:false,
+							canonical: {
+      				  Image:
+      				    /^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i,
+      				  File: /^https?:\/\/(.+\/)+.+(\.(docx|xlsx|ppt|pdf))$/i,
+      				},
+							updateFile:{
+								url:"",
+								fileName:""
+							},
             }
         },
         methods: {
@@ -300,6 +492,7 @@
               .get(this.$store.state.api+'/studentProjectData',param)
               .then(res=>{
                 let data=res.data[0][0];
+									this.loading = false;
                   console.log(data);
                   let wordData={}
                   wordData.projectName=data.title;
@@ -319,12 +512,58 @@
                   wordData.introduce=JSON.parse(data.chapters)
                   wordData.fund=JSON.parse(data.money)
                   wordData.dp=data.className
+									wordData.attachment = data.attachment?JSON.parse(data.attachment):[]
                   this.downWordData=wordData
-									this.loading = false;
+									
               },err=>{
                   console.log(err);
               })
           },
+					//展示文件
+    			checkFile(url) {
+    			  this.videoDetail = {};
+    			  if (
+    			    this.vedio.indexOf(
+    			      url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			    ) != -1
+    			  ) {
+    			    this.playerOptions.sources[0].src = url;
+    			    this.videoDetail = this.playerOptions;
+    			    this.showFile = true;
+    			  } else {
+    			    if (
+    			      this.word.indexOf(
+    			        url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			      ) == -1 &&
+    			      this.pdf.indexOf(
+    			        url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			      ) == -1 &&
+    			      this.image.indexOf(
+    			        url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			      ) == -1
+    			    ) {
+    			      this.downFile(url);
+    			      return;
+    			    }
+    			    this.showFileUrl = url;
+    			    this.showFile = true;
+    			    if (typeof url == "undefined") return { type: "", name: "" };
+    			    let urlSplit = url.split(".");
+    			    const type = urlSplit[urlSplit.length - 1];
+    			    if (this.canonical.Image.test(url)) {
+    			      this.Wordss = { type: type, name: "图片" };
+    			      return console.log(this.Wordss);
+    			    }
+    			    if (this.canonical.File.test(url)) {
+    			      this.Wordss = { type: type, name: "文档" };
+    			      return console.log(this.Wordss);
+    			    }
+    			    if (this.canonical.vedio.test(url)) {
+    			      this.Wordss = { type: type, name: "视频" };
+    			      return console.log(this.Wordss);
+    			    } else return (this.Wordss = { type: type, name: type });
+    			  }
+    			},
         },
         computed:{   //经费总合
           reversedMessage: function () {
@@ -464,5 +703,157 @@
         }
 
       }
-    
+			.operate {
+  right: -85px;
+  width: 85px;
+  height: 50px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  position: absolute;
+  .el-button {
+    max-width: 10px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin-left: 10px;
+  }
+}
+.noFileBox {
+  width: 98%;
+  min-height: 200px;
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+}
+.bigBlock {
+  width: 98%;
+  min-height: 200px;
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+  border: 1px solid #cad1dc;
+  border-radius: 4px;
+  padding: 10px;
+  .fileBlock {
+    width: 98%;
+    margin-right: 20px;
+    position: relative;
+    border-radius: 5%;
+    padding: 5px 0 5px 0;
+    border-bottom: 1px solid #cad1dc;
+    .fileBox {
+      display: flex;
+      flex-direction: row;
+      flex-wrap: nowrap;
+      justify-content: space-between;
+      align-items: center;
+
+      .fileBoxLeft {
+        cursor: pointer;
+        display: flex;
+        flex-direction: row;
+        flex-wrap: nowrap;
+        align-items: center;
+        .chapter_upload_l_i3 {
+          width: 15px;
+          height: 15px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          background-image: url("../../../assets/img/u_video.png");
+        }
+        .titName {
+          width: calc(100% - 15px);
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          word-break: break-word;
+          text-align: left;
+          margin-left: 10px;
+          max-width: 800px;
+        }
+      }
+      .fileBoxRight {
+        cursor: pointer;
+        display: flex;
+        flex-direction: row;
+        flex-wrap: nowrap;
+        align-items: center;
+        .chapter_upload_ud {
+          display: flex;
+          flex-direction: row;
+          justify-content: center;
+          margin: 0 10px 0 0;
+          .chapter_upload_up {
+            margin-right: 10px !important;
+          }
+          .chapter_upload_down,
+          .chapter_upload_up {
+            width: 20px;
+            height: 20px;
+            background: #e4eaf2;
+            cursor: pointer;
+            margin: 0 auto;
+            border-radius: 5px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+          }
+        }
+        .chapter_upload_up::after,
+        .chapter_upload_down::after {
+          content: "";
+          background-image: url("../../../assets/img/downBtn.png");
+          width: 13px;
+          height: 13px;
+          background-size: 100% 100%;
+          display: block;
+        }
+
+        .chapter_upload_up::after {
+          background-image: url("../../../assets/img/upBtn.png") !important;
+        }
+        .chapter_upload_ic_edit {
+          width: 18px;
+          height: 18px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          margin-right: 10px;
+          background-image: url("../../../assets/img/edit_u.png");
+        }
+        .chapter_upload_ic_r {
+          width: 18px;
+          height: 18px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          background-image: url("../../../assets/img/delete_u.png");
+        }
+      }
+    }
+  }
+  .masking-out {
+    width: 100px;
+    height: 135px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    display: none;
+    border-radius: 5%;
+    background: #00000053;
+    .delete {
+      cursor: pointer;
+      margin-left: 50%;
+      margin-top: 50%;
+      transform: translate(-50%, -50%);
+    }
+    .delete:hover {
+      color: #fff;
+    }
+  }
+  .fileBlock:hover .masking-out {
+    display: block;
+  }
+}
     </style>

+ 1 - 1
src/views/home.vue

@@ -304,7 +304,7 @@ export default {
         this.$store.state.userInfo.type == 4) {
 
         // this.$router.push("/resultsShow");
-				this.$router.push("/commission")
+				this.$router.push("/projectApplication")
       } else if (
         this.$store.state.userInfo.type == 5 ||
         this.$store.state.userInfo.type == 6

+ 5 - 5
src/views/projectApply/MakerSpaceApply.vue

@@ -401,11 +401,11 @@ export default {
 			this.ajax.get(this.$store.state.api + "/getDraft",params).then(res=>{
 				if(res.data[0].length){
 					this.wordData = JSON.parse(res.data[0][0].json)
-				}else{
-					if (localStorage.getItem(`MakerSpaceApplyData${this.$store.state.userInfo.userid}`))
-      		this.wordData = JSON.parse(
-      		  localStorage.getItem(`MakerSpaceApplyData${this.$store.state.userInfo.userid}`)
-      		);
+				// }else{
+				// 	if (localStorage.getItem(`MakerSpaceApplyData${this.$store.state.userInfo.userid}`))
+      	// 	this.wordData = JSON.parse(
+      	// 	  localStorage.getItem(`MakerSpaceApplyData${this.$store.state.userInfo.userid}`)
+      	// 	);
 				}
 				this.loading = false;
 			})

+ 89 - 2
src/views/projectApply/components/studentProjectWord.vue

@@ -516,6 +516,85 @@
             v-model="wordData.introduce.plan"
           ></editor-bar>
         </td>
+      </tr>
+			<tr>
+        <td class="bold">附件上传</td>
+        <td
+          colspan="6"
+          class="textLeft"
+          style="height: 200px; position: relative"
+        >
+          <!-- <el-button type="primary" style="position: absolute; right: 130px; top: 5px" v-if="![1,2].includes($store.state.userInfo.type) && wordData.courseId" @click="$emit('saveFile')">保存</el-button> -->
+          <beUpload
+            style="position: absolute; right: 10px; top: 5px"
+            @getFile="getFile2"
+            :navName="'上传文件'"
+            :accept="accept"
+            :progress="progress2"
+          ></beUpload>
+          <el-progress
+            v-if="progress2.show"
+            :percentage="progress2.value"
+            :format="ProgressFormat"
+            style="width: 80%"
+          ></el-progress>
+          <div
+            v-if="wordData.attachment"
+            :class="wordData.attachment.length > 0 ? 'bigBlock' : 'noFileBox'"
+          >
+            <div
+              class="fileBlock"
+              v-for="(item, index) in wordData.attachment"
+              :key="index + 'l'"
+            >
+              <div class="fileBox">
+                <div
+                  class="fileBoxLeft"
+                  @click="$emit('fileOption2', item, index, '0')"
+                >
+                  <!--  @click="checkFile(item.url)" -->
+                  <div class="chapter_upload_l_i3"></div>
+                  <div class="titName">{{ item.fileName }}</div>
+                </div>
+                <div
+                  class="fileBoxRight"
+                >
+                  <div class="chapter_upload_ud" style="z-index: 99">
+                    <div
+                      class="chapter_upload_up"
+                      @click="$emit('fileOption2', item, index, '1')"
+                    ></div>
+                    <div
+                      class="chapter_upload_down"
+                      @click="$emit('fileOption2', item, index, '2')"
+                    ></div>
+                  </div>
+                  <div
+                    class="chapter_upload_ic_edit"
+                    @click="$emit('fileOption2', item, index, '3')"
+                  ></div>
+                  <div
+                    class="chapter_upload_ic_r"
+                    @click="$emit('fileOption2', item, index, '4')"
+                  ></div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <!-- <div
+            style="
+              text-align: right;
+              font-size: 18px;
+              width: 80%;
+              margin-bottom: 20px;
+            "
+          >
+            负责人签章:
+          </div>
+          <div style="text-align: right; font-size: 18px; width: 90%">
+            年&nbsp;&nbsp;&nbsp; 月 &nbsp;&nbsp;&nbsp;日
+          </div> -->
+        </td>
       </tr>
       <tr id="fund">
         <td rowspan="12" ref="fund" class="bold">
@@ -891,7 +970,7 @@ import beUpload from "@/components/tool/beUpload";
 export default {
   components: { EditorBar, beUpload },
   props: ["wordData", "reversedMessage", "signData",'download'],
-  emit: ["getFile", "fileOption", "saveFile"],
+  emit: ["getFile","getFile2","fileOption","fileOption2", "saveFile"],
   data() {
     return {
       accept: "*",
@@ -899,6 +978,10 @@ export default {
         value: 0,
         show: false,
       },
+			progress2:{
+				value: 0,
+        show: false,
+			},
       DepartmentData: [], //部门学院
     };
   },
@@ -907,7 +990,11 @@ export default {
       this.$emit("getFile", file);
       this.progress.show = false;
     },
-    fileOption(file, index, opt) {},
+		getFile2(file) {
+      this.$emit("getFile2", file);
+      this.progress2.show = false;
+    },
+
     ProgressFormat(value) {
       //进度条
       return value == 100 ? "100%" : `${value}%`;

+ 248 - 35
src/views/projectApply/components/studentProjectWordDetail.vue

@@ -7,7 +7,9 @@
 			:signData="signData"
 			:download="loading"
 			@getFile="getFile"
+			@getFile2="getFile2"
 			@fileOption="fileOption"
+			@fileOption2="fileOption2"
 			@saveFile="saveFile"
     />
     <studentProjectWordShow
@@ -201,6 +203,36 @@
         <el-button @click="dialogVisibleUpdateFile = false">取 消</el-button>
         <el-button type="primary" @click="updateFileName">确 定</el-button>
       </span>
+    </el-dialog>
+
+		<!-- 修改文件名称2-->
+		<el-dialog
+      title="修改名称"
+      :visible.sync="dialogVisibleUpdateFile2"
+      :append-to-body="true"
+      width="500px"
+      class="dialog_diy"
+    >
+      <div
+        style="
+          width: 100%;
+          display: flex;
+          flex-direction: row;
+          flex-wrap: nowrap;
+          align-items: center;
+          justify-content: center;
+        "
+      >
+        <div style="min-width: fit-content">文件名称:</div>
+        <el-input
+          v-model="updateFile.fileName"
+          placeholder="请输入要修改的名称"
+        ></el-input>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisibleUpdateFile2 = false">取 消</el-button>
+        <el-button type="primary" @click="updateFileName2">确 定</el-button>
+      </span>
     </el-dialog>
   </div>
 </template>
@@ -213,6 +245,82 @@ import studentProjectWordShow from "./studentProjectWordShow.vue";
 import { downloadPDF } from "@/components/tool/pdf";
 import vpdf from "@/components/vpdf.vue";
 import vword from "@/components/vword.vue";
+import "@/components/common/aws-sdk-2.235.1.min.js"
+const getFile = (url) => {
+  return new Promise((resolve, reject) => {
+    var credentials = {
+        accessKeyId: "AKIATLPEDU37QV5CHLMH",
+        secretAccessKey: "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",
+      }; //秘钥形式的登录上传
+      window.AWS.config.update(credentials);
+      window.AWS.config.region = "cn-northwest-1"; //设置区域
+      let url2 = url;
+      let _url2 = "";
+      if (
+        url2.indexOf("https://view.officeapps.live.com/op/view.aspx?src=") != -1
+      ) {
+        _url2 = url2.split(
+          "https://view.officeapps.live.com/op/view.aspx?src="
+        )[1];
+      } else {
+        _url2 = url2;
+      }
+      var s3 = new window.AWS.S3({ params: { Bucket: "ccrb" } });
+      let name = decodeURIComponent(_url2.split("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/")[1])
+      var params = {
+        Bucket: "ccrb",
+        Key: name
+      };
+      s3.getObject(params, function (err, data) {
+        if (err) {
+          console.log(err, err.stack)
+          resolve({ data: 1 });
+        }else {
+          resolve({ data: data.Body });
+          console.log(data); 
+        }          // sxuccessful response
+
+      });
+  //     var credentials = {
+  //       accessKeyId: "AKIATLPEDU37QV5CHLMH",
+  //       secretAccessKey: "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",
+  //     }; //秘钥形式的登录上传
+  //     window.AWS.config.update(credentials);
+  //     window.AWS.config.region = "cn-northwest-1"; //设置区域
+  //     let url2 = url;
+  //     let _url2 = "";
+  //     if (
+  //       url2.indexOf("https://view.officeapps.live.com/op/view.aspx?src=") != -1
+  //     ) {
+  //       _url2 = url2.split(
+  //         "https://view.officeapps.live.com/op/view.aspx?src="
+  //       )[1];
+  //     } else {
+  //       _url2 = url2;
+  //     }
+  //     let _this = this;
+
+  //     var s3 = new window.AWS.S3({ params: { Bucket: "ccrb" } });
+  //     let name = decodeURIComponent(_url2.split("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/")[1])
+  //     var params = {
+  //       Bucket: "ccrb",
+  //       Key: name
+  //     };
+  //     s3.getObject(params, function (err, data) {
+  //       if (err) console.log(err, err.stack); // an error occurred
+  //       else {
+  //         let url = window.URL.createObjectURL(new Blob([data.Body]));
+  //         let a = document.createElement("a");
+  //         a.name = name;
+  //         a.href = url;
+  //         a.download = name;
+  //         a.click();
+  //         console.log(data);
+  //       }     // sxuccessful response
+
+  //     });
+  });
+};
 export default {
   components: { studentProjectWord, studentProjectWordShow,vword,vpdf },
   data() {
@@ -225,6 +333,7 @@ export default {
       updatedWordDig: false, //立即修改对话框
 			showFile:false,// 展示文件弹窗
 			dialogVisibleUpdateFile:false,//修改文件弹窗
+			dialogVisibleUpdateFile2:false,//修改文件弹窗2
       downWordData: {
         applicationDate: getNowDate(1), //申请日期
         projectName: "",
@@ -325,6 +434,7 @@ export default {
           activities: "",
           entery: "",
         },
+				attachment:[],//附件上传
 				opinion:[],
       },
 			signData:[],
@@ -501,6 +611,7 @@ export default {
           this.wordData.introduce = JSON.parse(data.chapters);
           this.wordData.fund = JSON.parse(data.money);
 					this.wordData.opinion = data.opinion?JSON.parse(data.opinion):[];
+					this.wordData.attachment = data.attachment?JSON.parse(data.attachment):[];
           this.downWordData = {
             ...this.wordData,
             ...{ etime: data.eTime, btime: data.bTime, dp: data.className },
@@ -519,7 +630,9 @@ export default {
 				pid:this.$route.query['pid']
 			}
 			this.ajax.get(this.$store.state.api+'/selectSign',params).then(res=>{
-				this.signData = res.data[0]
+				let signData = res.data[0]
+				signData.sort((a,b)=>new Date(b.create_at) - new Date(a.create_at))
+				this.signData = signData
 			})
 		},
     test() {
@@ -723,8 +836,8 @@ export default {
         mon: encodeURIComponent(JSON.stringify(this.wordData["fund"])), //预算经费
         f: this.wordData["total"], //总经费
         apply: this.wordData["applicationDate"], //申请日期
-        mem:
-          this.wordData["teacherS"].filter(i=>i.name!='').length + this.wordData["studentS"].filter(i=>i.name!='').length,
+        mem:this.wordData["teacherS"].filter(i=>i.name!='').length + this.wordData["studentS"].filter(i=>i.name!='').length,
+				attachment:encodeURIComponent(JSON.stringify(this.wordData["attachment"])),//附件上传
       };
       this.ajax
         .post(this.$store.state.api + "/updateStudentProjectData", param)
@@ -745,12 +858,55 @@ export default {
     },
 		downloadWordFile(){
 			this.loading = true;
-			
-			this.$nextTick(()=>{
+            // var credentials = {
+            //     accessKeyId: "AKIATLPEDU37QV5CHLMH",
+            //     secretAccessKey: "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",
+            // }; //秘钥形式的登录上传
+            // window.AWS.config.update(credentials);
+            // window.AWS.config.region = "cn-northwest-1"; //设置区域
+            // let url2 = "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%94%B6%E5%85%A5%E6%A8%A1%E5%BC%8F1712047315470.jpg";
+            // let _url2 = "";
+            // if (
+            //     url2.indexOf("https://view.officeapps.live.com/op/view.aspx?src=") != -1
+            // ) {
+            //     _url2 = url2.split(
+            //         "https://view.officeapps.live.com/op/view.aspx?src="
+            //     )[1];
+            // } else {
+            //     _url2 = url2;
+            // }
+            // let _this = this;
+
+            // var s3 = new window.AWS.S3({ params: { Bucket: "ccrb" } });
+            // let name = decodeURIComponent(_url2.split("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/")[1])
+            // var params = {
+            //     Bucket: "ccrb",
+            //     Key: name
+            // };
+            // s3.getObject(params, function (err, data) {
+  
+            //     if (err) console.log(err, err.stack); // an error occurred
+            //     else {
+            //         let url = window.URL.createObjectURL(new Blob([data.Body]));
+            //         let a = document.createElement("a");
+            //         a.name = name;
+            //         a.href = url;
+            //         a.download = name;
+            //         a.click();
+            //         console.log(data);
+            //     }          // sxuccessful response
+
+            // });
+			// getFile("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E5%9B%BE%E7%89%8711711980299371.jpg").then(res=>{
+			// 	console.log(res)
+			// })
+			// return
+			this.$nextTick(async ()=>{
 				this.$message.info("正在下载,请稍等...")
 				let elementList = this.$refs.myChild.$refs.pdfShow.querySelectorAll('.downImage')
 				let fontSize = [];
 				let pFontSize = [];
+				let promises = []
 				let fontType = {
 					'1':"13pt",
 					'2':"16.9pt",
@@ -763,7 +919,25 @@ export default {
 				elementList.forEach((el,elIndex) => {
 				  let img = el.getElementsByTagName('img');
 					for(let i=0;i<img.length;i++){
-						img[i].setAttribute("crossOrigin","*");
+						// img[i].setAttribute('crossOrigin',"*")
+						// let src = img[i].getAttribute("src");
+						// promises.push(getFile(src).then(async res=>{
+						// 	await new Promise(resolve => {
+						// 	  if (res.data != 1) {
+						// 			let blob = new Blob([res.data]);
+						// 			// blob = new Blob([res.data],{type:res.headers['content-type']});
+						// 			let reader = new FileReader();
+						// 			reader.readAsDataURL(blob);
+						// 			reader.onload = function(e){
+						// 				img[i].setAttribute("src",this.result);
+						// 				resolve();
+						// 			}
+          	// 		}
+						// 	})
+							
+						// }))
+						
+						// img[i].setAttribute("crossOrigin","*");
 					}
 					let font = el.getElementsByTagName('font');
 					for(let i=0;i<font.length;i++){
@@ -788,37 +962,42 @@ export default {
 						p[i].setAttribute("style",newStyle)
 					}
 				})
-				let newData = JSON.parse(JSON.stringify(this.downWordData))
-				getWord2({...newData,signData:this.signData,elementList}).then(_=>{
-					elementList.forEach((el,elIndex) => {
-				  	let img = el.getElementsByTagName('img');
-						for(let i=0;i<img.length;i++){
-							img[i].removeAttribute('crossOrigin')
-						}
-						let font = el.getElementsByTagName('font');
-						for(let i=0;i<font.length;i++){
-							font[i].removeAttribute("style")
-							font[i].setAttribute("size",fontSize[i])
-						}
-						// 替换p标签的font-size
-						let p = el.querySelectorAll("*")
-						for(let i=0;i<p.length;i++){
-							let oldStyle = pFontSize.find(p=>p.index==`${elIndex}:${i}`)
-							if(!oldStyle)continue;
-							p[i].setAttribute("style",oldStyle.style)
-							// let pStyle = p[i].getAttribute("style")
-					
-							// if(!pStyle)continue
-							// let matchArr = pStyle.match(/font-size: (\d+)px/);
-							// console.log(matchArr)
-							// if(!matchArr)continue;
-							// console.log(pFontSize[i])
-							// p[i].setAttribute("style",pFontSize[i])
-						}
+				// return
+				// return await Promise.all(promises)
+				Promise.all(promises).then(()=>{
+					let newData = JSON.parse(JSON.stringify(this.downWordData))
+					getWord2({...newData,signData:this.signData,elementList}).then(_=>{
+						elementList.forEach((el,elIndex) => {
+					  	let img = el.getElementsByTagName('img');
+							for(let i=0;i<img.length;i++){
+								img[i].removeAttribute('crossOrigin')
+							}
+							let font = el.getElementsByTagName('font');
+							for(let i=0;i<font.length;i++){
+								font[i].removeAttribute("style")
+								font[i].setAttribute("size",fontSize[i])
+							}
+							// 替换p标签的font-size
+							let p = el.querySelectorAll("*")
+							for(let i=0;i<p.length;i++){
+								let oldStyle = pFontSize.find(p=>p.index==`${elIndex}:${i}`)
+								if(!oldStyle)continue;
+								p[i].setAttribute("style",oldStyle.style)
+								// let pStyle = p[i].getAttribute("style")
+							
+								// if(!pStyle)continue
+								// let matchArr = pStyle.match(/font-size: (\d+)px/);
+								// console.log(matchArr)
+								// if(!matchArr)continue;
+								// console.log(pFontSize[i])
+								// p[i].setAttribute("style",pFontSize[i])
+							}
+						})
+						this.downloadWordDig = false;
+						this.loading = false;
 					})
-					this.downloadWordDig = false;
-					this.loading = false;
 				})
+				
 			})
 			
 			
@@ -885,6 +1064,34 @@ export default {
 				})
 			}
 		},
+		//上传附件
+		fileOption2(file,index,opt){
+			if(opt=='0'){
+				this.checkFile(file.url)
+			}else if(opt=='1'){
+				if(index==0)return;
+				this.wordData.attachment.splice(index-1,0,this.wordData.attachment.splice(index,1)[0]);
+			}else if(opt=='2'){
+				if(index==this.wordData.attachment.length-1)return;
+				this.wordData.attachment.splice(index+1,0,this.wordData.attachment.splice(index,1)[0]);
+			}else if(opt=='3'){
+				this.updateFile = {...file,index:index}
+				this.dialogVisibleUpdateFile2 = true;
+				
+			}else if(opt=='4'){
+				this.$confirm("确定删除该文件?","提示",{
+					type:"error",
+					confirmButtonText:"确定删除",
+					cancelButtonText:"取消",
+				}).then(_=>{
+					this.wordData.attachment.splice(index,1);
+				})
+			}
+		},
+		// 上传专家文件
+		getFile2(file){
+			this.wordData.attachment.push(file);
+		},
 		// 上传文件函数
 		saveFile(){
 			let params = {
@@ -950,6 +1157,12 @@ export default {
 			this.wordData.opinion[this.updateFile.index].fileName = this.updateFile.fileName;
 			this.dialogVisibleUpdateFile = false;
 			this.saveFile();
+		},
+		// 修改文件名称
+		updateFileName2(){
+			if(!this.updateFile.fileName)return this.$message.error("请输入文件名称");
+			this.wordData.attachment[this.updateFile.index].fileName = this.updateFile.fileName;
+			this.dialogVisibleUpdateFile2 = false;
 		}
 		// downloadWord2() {
     //   // downloadPDF(

+ 27 - 0
src/views/projectApply/components/studentProjectWordShow.vue

@@ -408,6 +408,33 @@
             v-html="downWordData.introduce.plan"
           ></span>
         </td>
+      </tr>
+			<tr>
+        <td><span class="jc">附件上传</span></td>
+        <td colspan="6" class="textLeft">
+          <!-- <el-button type="primary" style="position: absolute; right: 130px; top: 5px" v-if="![1,2].includes($store.state.userInfo.type)" @click="$emit('saveFile')">保存</el-button> -->
+
+          <div
+					style="margin:0"
+            :class="downWordData.attachment.length > 0 ? 'bigBlock' : 'noFileBox'"
+          >
+            <div
+              class="fileBlock"
+              v-for="(item, index) in downWordData.attachment"
+              :key="index + 'l'"
+            >
+              <div class="fileBox">
+                <div
+                  class="fileBoxLeft"
+                  @click="$emit('fileOption', item, index, '0')"
+                >
+                  <div class="chapter_upload_l_i3"></div>
+                  <div class="titName">{{ item.fileName }}</div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </td>
       </tr>
       <tr id="fund">
         <td rowspan="12" ref="fund">

+ 293 - 15
src/views/projectApply/newStudentProjectApply.vue

@@ -11,12 +11,15 @@
       ref="pdf"
       :wordData="wordData"
       :reversedMessage="reversedMessage"
+			@fileOption2="fileOption2"
+			@getFile2="getFile2"
     />
     <div style="position: fixed; bottom: 5%; right: 2%">
 			<el-button @click="saveDraft" type="primary">保存草稿</el-button>
       <el-button @click="test" type="primary">保存项目</el-button>
     </div>
 
+		<!-- 保存项目弹窗 -->
     <el-dialog
       title="提示"
       :visible.sync="submitHint"
@@ -34,6 +37,82 @@
           >取消</el-button
         >
       </span>
+    </el-dialog>
+
+				<!-- 展示文件 -->
+				<el-dialog
+      title="展示文件"
+      :visible.sync="showFile"
+      top="1vh"
+      width="80vw"
+      append-to-body
+    >
+      <div class="showFileArea" style="height: 80vh">
+        <!-- <vpdf v-if="/^\s*$/g.test(showFileUrl)&&showFileUrl.split('.')[showFileUrl.split('.').length-1]=='pdf'" :pdfUrl="showFileUrl"></vpdf> -->
+        <div
+          class="workd_media"
+          style="width: 90%; height: 90%"
+          v-if="videoDetail.sources"
+        >
+          <video-player
+            class="video-player vjs-custom-skin"
+            :playsinline="true"
+            :options="videoDetail"
+            @play="onPlayerPlay($event)"
+            style="width: 90%; height: 90%; margin: 0 auto"
+          ></video-player>
+        </div>
+        <vword
+          style="width: 100%; height: 100%; overflow: auto"
+          class="fullStyle"
+          v-else-if="Wordss['type'] != 'pdf' && Wordss['name'] != '图片'"
+          :pdfUrl="
+            'https://view.officeapps.live.com/op/view.aspx?src=' + showFileUrl
+          "
+        ></vword>
+        <vpdf
+          style="width: 100%; height: 100%; overflow: auto"
+          class="fullStyle"
+          :pdfUrl="showFileUrl"
+          v-else-if="Wordss['type'] == 'pdf'"
+        ></vpdf>
+        <img
+          :src="showFileUrl"
+          alt="图片哦"
+          v-else-if="Wordss['name'] == '图片'"
+          style="width: auto; height: auto; max-width: 100%; max-height: 100%"
+        />
+      </div>
+      <!-- <el-button type="primary" size="mini" @click="downFile(showFileUrl)">下载文件</el-button> -->
+    </el-dialog>
+		<!-- 修改文件名称 -->
+		<el-dialog
+      title="修改名称"
+      :visible.sync="dialogVisibleUpdateFile"
+      :append-to-body="true"
+      width="500px"
+      class="dialog_diy"
+    >
+      <div
+        style="
+          width: 100%;
+          display: flex;
+          flex-direction: row;
+          flex-wrap: nowrap;
+          align-items: center;
+          justify-content: center;
+        "
+      >
+        <div style="min-width: fit-content">文件名称:</div>
+        <el-input
+          v-model="updateFile.fileName"
+          placeholder="请输入要修改的名称"
+        ></el-input>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisibleUpdateFile = false">取 消</el-button>
+        <el-button type="primary" @click="updateFileName">确 定</el-button>
+      </span>
     </el-dialog>
   </div>
 </template>
@@ -43,11 +122,15 @@
 import getProjectNo from "@/components/tool/getProjectNo";
 import { getNowDate } from "@/components/tool/Date.js";
 import studentProjectWord from "./components/studentProjectWord.vue";
+import vpdf from "@/components/vpdf.vue";
+import vword from "@/components/vword.vue";
 // import markerFundWord from '@/components/markerFundWord.vue';
 // import markeractivityWord from '@/components/markeractivityWord.vue';
 export default {
   components: {
     studentProjectWord,
+		vpdf,
+		vword
     // markerFundWord,
     // markeractivityWord
   },
@@ -56,6 +139,112 @@ export default {
       accept: "*",
       loading: false,
       submitHint: false,
+			updatedWordDig: false, //立即修改对话框
+			showFile:false,// 展示文件弹窗
+			dialogVisibleUpdateFile:false,//修改文件弹窗
+			word: [
+        "DOC",
+        "DOCX",
+        "DOCM",
+        "DOTM",
+        "DOTX",
+        "PPTX",
+        "PPSX",
+        "PPT",
+        "PPS",
+        "PPTM",
+        "POTM",
+        "PPAM",
+        "POTX",
+        "PPSM",
+        "XLSX",
+        "XLS",
+      ],
+      pdf: ["PDF"],
+      image: [
+        "BMP",
+        "PJP",
+        "APNG",
+        "PNG",
+        "JPG",
+        "GIF",
+        "SVG",
+        "JPEG",
+        "JPG",
+        "ICO",
+        "PGPEG",
+        "AVIF",
+      ],
+      vedio: [
+        "AVI",
+        "NAVI",
+        "MPEG",
+        "ASF",
+        "MOV",
+        "WMV",
+        "3GP",
+        "RM",
+        "RMVB",
+        "FLV",
+        "F4V",
+        "H.264",
+        "H.265",
+        "REAL VIDEO",
+        "MKV",
+        "WebM",
+        "HDDVD",
+        "MP4",
+        "MPG",
+        "M4V",
+        "MGV",
+        "OGV",
+        "QTM",
+        "STR",
+        "AMC",
+        "DVX",
+        "EVO",
+        "DAT",
+        "OGG",
+        "OGM",
+      ],
+      playerOptions: {
+        playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
+        autoplay: false, //如果true,浏览器准备好时开始回放。
+        muted: false, // 默认情况下将会消除任何音频。
+        loop: false, // 导致视频一结束就重新开始。
+        preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+        language: "zh-CN",
+        aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+        fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+        sources: [
+          {
+            type: "video/mp4", //这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目   || "video/ogg"|| "video/webm"
+            src: "", //url地址require("../../assets/media/aaa.mp4")
+          },
+        ],
+        // poster: require("../../assets/tu31.png"), //你的封面地址
+        // poster: dataRes.imgUrl, //你的封面地址
+        notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
+        controlBar: {
+          timeDivider: true, //当前时间和持续时间的分隔符
+          durationDisplay: true, //显示持续时间
+          remainingTimeDisplay: false, //是否显示剩余时间功能
+          fullscreenToggle: true, //全屏按钮
+        },
+      },
+      playerO: {},
+      videoDetail: {},
+			Wordss:{},
+			showFileUrl:"",
+			canonical: {
+        Image:
+          /^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i,
+        File: /^https?:\/\/(.+\/)+.+(\.(docx|xlsx|ppt|pdf))$/i,
+      },
+			updateFile:{
+				url:"",
+				fileName:""
+			},
       wordData: {
         applicationDate: getNowDate(1), //申请日期
         projectName: "",
@@ -99,6 +288,7 @@ export default {
           expectConversion: "",
           plan: "",
         },
+				attachment:[],
         total: "",
         fund: {
           device: "",
@@ -315,7 +505,13 @@ export default {
     submitWord() {
       //提交
       // return console.log(this.wordData['total']);
-      getProjectNo("XM").then((result) => {
+			let typeList = {
+				"4a4e2cfe-e1a1-11ee-81d4-00ff5c7a43f5":"CX",
+				"56f0ad8d-e1a1-11ee-81d4-00ff5c7a43f5":"CY",
+				"ed917c55-f51d-11ed-a3f6-509a4c5b67cf":"SJ",
+				"1":"XM"
+			}
+      getProjectNo(typeList[this.wordData["radio"]]).then((result) => {
         let pram = {
           uid: this.$store.state.userInfo.userid, //用户ID
           pNo: result, //项目编号
@@ -337,10 +533,9 @@ export default {
           mon: encodeURIComponent(JSON.stringify(this.wordData["fund"])), //预算经费
           f: this.wordData["total"], //总经费
           apply: this.wordData["applicationDate"], //申请日期
-          mem:
-            this.wordData["studentS"].filter(i=>i.name!='').length + this.wordData["teacherS"].filter(i=>i.name!='').length, //项目组人数
+          mem:this.wordData["studentS"].filter(i=>i.name!='').length + this.wordData["teacherS"].filter(i=>i.name!='').length, //项目组人数
+					attachment:encodeURIComponent(JSON.stringify(this.wordData["attachment"])),//附件上传
         };
-        // return
         this.ajax
           .post(this.$store.state.api + "/studentProjectWordApply", pram)
           .then(
@@ -349,11 +544,15 @@ export default {
               if (result["data"] == 1) {
                 this.$message.success("项目提交成功");
                 //提交项目成功,查看sessionStore是否有数据,有则删
-								localStorage.removeItem(`StudentProjectApplyData${this.$store.state.userInfo.userid}`);
+								// localStorage.removeItem(`StudentProjectApplyData${this.$store.state.userInfo.userid}`);
                 await this.ajax.post(this.$store.state.api+"/delDraft",{userid:this.$store.state.userInfo.userid,type:0})
+								this.submitHint = false;
+								this.$destroy();
                 this.$router.push("/projectApplication");
+								
               } else {
                 this.$message.error("项目提交失败");
+								this.submitHint = false
               }
             },
             (err) => {
@@ -366,10 +565,10 @@ export default {
       });
     },
     saveData() {
-      localStorage.setItem(
-        `StudentProjectApplyData${this.$store.state.userInfo.userid}`,
-        JSON.stringify(this.wordData)
-      );
+      // localStorage.setItem(
+      //   `StudentProjectApplyData${this.$store.state.userInfo.userid}`,
+      //   JSON.stringify(this.wordData)
+      // );
     },
 		// 保存草稿
 		saveDraft(){
@@ -400,15 +599,94 @@ export default {
 			this.ajax.get(this.$store.state.api + "/getDraft",params).then(res=>{
 				if(res.data[0].length){
 					this.wordData = JSON.parse(res.data[0][0].json)
-				}else{
-					if (localStorage.getItem(`StudentProjectApplyData${this.$store.state.userInfo.userid}`)){
-						this.wordData = JSON.parse(
-      			  localStorage.getItem(`StudentProjectApplyData${this.$store.state.userInfo.userid}`)
-      			);
-					}
+				// }else{
+				// 	if (localStorage.getItem(`StudentProjectApplyData${this.$store.state.userInfo.userid}`)){
+				// 		this.wordData = JSON.parse(
+      	// 		  localStorage.getItem(`StudentProjectApplyData${this.$store.state.userInfo.userid}`)
+      	// 		);
+				// 	}
 				}
 				this.loading = false;
 			})
+		},
+		//上传附件
+		fileOption2(file,index,opt){
+			if(opt=='0'){
+				this.checkFile(file.url)
+			}else if(opt=='1'){
+				if(index==0)return;
+				this.wordData.attachment.splice(index-1,0,this.wordData.attachment.splice(index,1)[0]);
+			}else if(opt=='2'){
+				if(index==this.wordData.attachment.length-1)return;
+				this.wordData.attachment.splice(index+1,0,this.wordData.attachment.splice(index,1)[0]);
+			}else if(opt=='3'){
+				this.updateFile = {...file,index:index}
+				this.dialogVisibleUpdateFile = true;
+				
+			}else if(opt=='4'){
+				this.$confirm("确定删除该文件?","提示",{
+					type:"error",
+					confirmButtonText:"确定删除",
+					cancelButtonText:"取消",
+				}).then(_=>{
+					this.wordData.attachment.splice(index,1);
+				})
+			}
+		},
+		// 上传专家文件
+		getFile2(file){
+			this.wordData.attachment.push(file);
+		},
+		// 展示文件
+		checkFile(url) {
+      this.videoDetail = {};
+      if (
+        this.vedio.indexOf(
+          url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+        ) != -1
+      ) {
+        this.playerOptions.sources[0].src = url;
+        this.videoDetail = this.playerOptions;
+        this.showFile = true;
+      } else {
+        if (
+          this.word.indexOf(
+            url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+          ) == -1 &&
+          this.pdf.indexOf(
+            url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+          ) == -1 &&
+          this.image.indexOf(
+            url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+          ) == -1
+        ) {
+          this.downFile(url);
+          return;
+        }
+        this.showFileUrl = url;
+        this.showFile = true;
+        if (typeof url == "undefined") return { type: "", name: "" };
+        let urlSplit = url.split(".");
+        const type = urlSplit[urlSplit.length - 1];
+        if (this.canonical.Image.test(url)) {
+          this.Wordss = { type: type, name: "图片" };
+          return console.log(this.Wordss);
+        }
+        if (this.canonical.File.test(url)) {
+          this.Wordss = { type: type, name: "文档" };
+          return console.log(this.Wordss);
+        }
+        if (this.canonical.vedio.test(url)) {
+          this.Wordss = { type: type, name: "视频" };
+          return console.log(this.Wordss);
+        } else return (this.Wordss = { type: type, name: type });
+      }
+    },
+		// 修改文件名称
+		updateFileName(){
+			if(!this.updateFile.fileName)return this.$message.error("请输入文件名称");
+			this.wordData.attachment[this.updateFile.index].fileName = this.updateFile.fileName;
+			this.dialogVisibleUpdateFile = false;
 		}
   },
   mounted() {

+ 21 - 2
src/views/projectApply/projectApplication.vue

@@ -899,6 +899,7 @@ export default {
 
 						_data.forEach((item, index)=>{
 							let _json = {};
+							let teacher = item.course_teacher?JSON.parse(item.course_teacher):[]
 							_json["项目编号"] = item.ProjectNo;
         			_json["项目名称"] = item.title;
         			_json["项目负责人"] = item.pro_leader;
@@ -907,8 +908,10 @@ export default {
         			_json["预算(万)"] = item.fund / 10000;
         			_json["创建时间"] = item.createTime;
         			_json["联系电话"] = item.phone;
-							
-        			_json["项目状态"] = this.classType[item.isupload];
+        			_json["项目状态"] = item.isReturn==0?this.classType[item.isupload]:this.isReturnType[item.isReturn];
+							for(let i =0;i<teacher.length;i++){
+								_json["指导老师"+(i+1)] = teacher[i].name;
+							}
 
 							_array.push(_json)
 						})
@@ -927,6 +930,22 @@ export default {
      + 			  { wch: 30 },
       			  { wch: 20 },
 							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
+							{ wch: 10 },
       			];
 						XLSX.utils.book_append_sheet(workbook, ws, "sheet1"); //把sheet添加到workbook里,第三个参数是sheet名
       			XLSX.writeFile(workbook,"项目列表.xlsx");

+ 366 - 2
src/views/projectManage/components/studentProjectWordShow.vue

@@ -220,6 +220,36 @@
           <span v-html="downWordData.introduce.plan"></span>
         </td>
       </tr>
+			<tr>
+        <td class="bold">附件上传</td>
+      	  <td
+      	    colspan="6"
+      	    class="textLeft"
+      	    style="height: 200px; position: relative"
+      	  >
+      	    <!-- <el-button type="primary" style="position: absolute; right: 130px; top: 5px" v-if="![1,2].includes($store.state.userInfo.type) && wordData.courseId" @click="$emit('saveFile')">保存</el-button> -->
+      	    <div
+      	      v-if="downWordData.attachment"
+      	      :class="downWordData.attachment.length > 0 ? 'bigBlock' : 'noFileBox'"
+      	    >
+      	      <div
+      	        class="fileBlock"
+      	        v-for="(item, index) in downWordData.attachment"
+      	        :key="index + 'l'"
+      	      >
+      	        <div class="fileBox">
+      	          <div
+      	            class="fileBoxLeft"
+      	            @click="checkFile(item.url)"
+      	          >
+      	            <div class="chapter_upload_l_i3"></div>
+      	            <div class="titName">{{ item.fileName }}</div>
+      	          </div>
+      	        </div>
+      	      </div>
+      	    </div>
+      	  </td>
+      	</tr>
       <tr id="fund">
         <td rowspan="12" ref="fund">预算经费</td>
         <td>总经费</td>
@@ -326,18 +356,169 @@
         <span>2.优先支持项目需提供与研发项目相关的实证材料并查看原件。</span>
       </div>
     </table>
-
+		<el-dialog
+				title="展示文件"
+				:visible.sync="showFile"
+				top="1vh"
+				width="80vw"
+				append-to-body
+				>
+				<div class="showFileArea" style="height: 80vh">
+				<!-- <vpdf v-if="/^\s*$/g.test(showFileUrl)&&showFileUrl.split('.')[showFileUrl.split('.').length-1]=='pdf'" :pdfUrl="showFileUrl"></vpdf> -->
+				<div
+					class="workd_media"
+					style="width: 90%; height: 90%"
+					v-if="videoDetail.sources"
+				>
+					<video-player
+						class="video-player vjs-custom-skin"
+						:playsinline="true"
+						:options="videoDetail"
+						@play="onPlayerPlay($event)"
+						style="width: 90%; height: 90%; margin: 0 auto"
+					></video-player>
+				</div>
+				<vword
+					style="width: 100%; height: 100%; overflow: auto"
+					class="fullStyle"
+					v-else-if="Wordss['type'] != 'pdf' && Wordss['name'] != '图片'"
+					:pdfUrl="
+						'https://view.officeapps.live.com/op/view.aspx?src=' + showFileUrl
+					"
+				></vword>
+				<vpdf
+					style="width: 100%; height: 100%; overflow: auto"
+					class="fullStyle"
+					:pdfUrl="showFileUrl"
+					v-else-if="Wordss['type'] == 'pdf'"
+				></vpdf>
+				<img
+					:src="showFileUrl"
+					alt="图片哦"
+					v-else-if="Wordss['name'] == '图片'"
+					style="width: auto; height: auto; max-width: 100%; max-height: 100%"
+				/>
+				</div>
+				<!-- <el-button type="primary" size="mini" @click="downFile(showFileUrl)">下载文件</el-button> -->
+				</el-dialog>
     <!-- <el-button style="margin-top:20px" type="primary" @click="work">下载表格</el-button> -->
   </div>
 </template>
       
     <script>
 import { getWord } from "@/components/tool/getWord";
+import vpdf from "@/components/vpdf.vue";
+import vword from "@/components/vword.vue";
 export default {
+	components:{vpdf,vword},
   data() {
     return {
       downWordData: {},
-			loading:false
+			loading:false,
+			word: [
+      				  "DOC",
+      				  "DOCX",
+      				  "DOCM",
+      				  "DOTM",
+      				  "DOTX",
+      				  "PPTX",
+      				  "PPSX",
+      				  "PPT",
+      				  "PPS",
+      				  "PPTM",
+      				  "POTM",
+      				  "PPAM",
+      				  "POTX",
+      				  "PPSM",
+      				  "XLSX",
+      				  "XLS",
+      				],
+      				pdf: ["PDF"],
+      				image: [
+      				  "BMP",
+      				  "PJP",
+      				  "APNG",
+      				  "PNG",
+      				  "JPG",
+      				  "GIF",
+      				  "SVG",
+      				  "JPEG",
+      				  "JPG",
+      				  "ICO",
+      				  "PGPEG",
+      				  "AVIF",
+      				],
+      				vedio: [
+      				  "AVI",
+      				  "NAVI",
+      				  "MPEG",
+      				  "ASF",
+      				  "MOV",
+      				  "WMV",
+      				  "3GP",
+      				  "RM",
+      				  "RMVB",
+      				  "FLV",
+      				  "F4V",
+      				  "H.264",
+      				  "H.265",
+      				  "REAL VIDEO",
+      				  "MKV",
+      				  "WebM",
+      				  "HDDVD",
+      				  "MP4",
+      				  "MPG",
+      				  "M4V",
+      				  "MGV",
+      				  "OGV",
+      				  "QTM",
+      				  "STR",
+      				  "AMC",
+      				  "DVX",
+      				  "EVO",
+      				  "DAT",
+      				  "OGG",
+      				  "OGM",
+      				],
+      				playerOptions: {
+      				  playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
+      				  autoplay: false, //如果true,浏览器准备好时开始回放。
+      				  muted: false, // 默认情况下将会消除任何音频。
+      				  loop: false, // 导致视频一结束就重新开始。
+      				  preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+      				  language: "zh-CN",
+      				  aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+      				  fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+      				  sources: [
+      				    {
+      				      type: "video/mp4", //这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目   || "video/ogg"|| "video/webm"
+      				      src: "", //url地址require("../../assets/media/aaa.mp4")
+      				    },
+      				  ],
+      				  // poster: require("../../assets/tu31.png"), //你的封面地址
+      				  // poster: dataRes.imgUrl, //你的封面地址
+      				  notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
+      				  controlBar: {
+      				    timeDivider: true, //当前时间和持续时间的分隔符
+      				    durationDisplay: true, //显示持续时间
+      				    remainingTimeDisplay: false, //是否显示剩余时间功能
+      				    fullscreenToggle: true, //全屏按钮
+      				  },
+      				},
+      				playerO: {},
+      				videoDetail: {},
+							Wordss:{},
+							showFileUrl:"",
+							showFile:false,
+							canonical: {
+      				  Image:
+      				    /^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i,
+      				  File: /^https?:\/\/(.+\/)+.+(\.(docx|xlsx|ppt|pdf))$/i,
+      				},
+							updateFile:{
+								url:"",
+								fileName:""
+							},
     };
   },
   methods: {
@@ -375,6 +556,7 @@ export default {
           wordData.introduce = JSON.parse(data.chapters);
           wordData.fund = JSON.parse(data.money);
           wordData.dp = data.className;
+					wordData.attachment = data.attachment?JSON.parse(data.attachment):[]
 
           this.downWordData = wordData;
 					
@@ -384,6 +566,51 @@ export default {
           console.log(err);
         }
       );
+    },
+		//展示文件
+		checkFile(url) {
+    			  this.videoDetail = {};
+    			  if (
+    			    this.vedio.indexOf(
+    			      url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			    ) != -1
+    			  ) {
+    			    this.playerOptions.sources[0].src = url;
+    			    this.videoDetail = this.playerOptions;
+    			    this.showFile = true;
+    			  } else {
+    			    if (
+    			      this.word.indexOf(
+    			        url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			      ) == -1 &&
+    			      this.pdf.indexOf(
+    			        url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			      ) == -1 &&
+    			      this.image.indexOf(
+    			        url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			      ) == -1
+    			    ) {
+    			      this.downFile(url);
+    			      return;
+    			    }
+    			    this.showFileUrl = url;
+    			    this.showFile = true;
+    			    if (typeof url == "undefined") return { type: "", name: "" };
+    			    let urlSplit = url.split(".");
+    			    const type = urlSplit[urlSplit.length - 1];
+    			    if (this.canonical.Image.test(url)) {
+    			      this.Wordss = { type: type, name: "图片" };
+    			      return console.log(this.Wordss);
+    			    }
+    			    if (this.canonical.File.test(url)) {
+    			      this.Wordss = { type: type, name: "文档" };
+    			      return console.log(this.Wordss);
+    			    }
+    			    if (this.canonical.vedio.test(url)) {
+    			      this.Wordss = { type: type, name: "视频" };
+    			      return console.log(this.Wordss);
+    			    } else return (this.Wordss = { type: type, name: type });
+    			  }
     },
   },
   computed: {
@@ -525,4 +752,141 @@ export default {
     }
   }
 }
+.noFileBox {
+  width: 98%;
+  min-height: 200px;
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+}
+.bigBlock {
+  width: 98%;
+  min-height: 200px;
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+  border: 1px solid #cad1dc;
+  border-radius: 4px;
+  padding: 10px;
+  .fileBlock {
+    width: 98%;
+    margin-right: 20px;
+    position: relative;
+    border-radius: 5%;
+    padding: 5px 0 5px 0;
+    border-bottom: 1px solid #cad1dc;
+    .fileBox {
+      display: flex;
+      flex-direction: row;
+      flex-wrap: nowrap;
+      justify-content: space-between;
+      align-items: center;
+
+      .fileBoxLeft {
+        cursor: pointer;
+        display: flex;
+        flex-direction: row;
+        flex-wrap: nowrap;
+        align-items: center;
+        .chapter_upload_l_i3 {
+          width: 15px;
+          height: 15px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          background-image: url("../../../assets/img/u_video.png");
+        }
+        .titName {
+          width: calc(100% - 15px);
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          word-break: break-word;
+          text-align: left;
+          margin-left: 10px;
+          max-width: 800px;
+        }
+      }
+      .fileBoxRight {
+        cursor: pointer;
+        display: flex;
+        flex-direction: row;
+        flex-wrap: nowrap;
+        align-items: center;
+        .chapter_upload_ud {
+          display: flex;
+          flex-direction: row;
+          justify-content: center;
+          margin: 0 10px 0 0;
+          .chapter_upload_up {
+            margin-right: 10px !important;
+          }
+          .chapter_upload_down,
+          .chapter_upload_up {
+            width: 20px;
+            height: 20px;
+            background: #e4eaf2;
+            cursor: pointer;
+            margin: 0 auto;
+            border-radius: 5px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+          }
+        }
+        .chapter_upload_up::after,
+        .chapter_upload_down::after {
+          content: "";
+          background-image: url("../../../assets/img/downBtn.png");
+          width: 13px;
+          height: 13px;
+          background-size: 100% 100%;
+          display: block;
+        }
+
+        .chapter_upload_up::after {
+          background-image: url("../../../assets/img/upBtn.png") !important;
+        }
+        .chapter_upload_ic_edit {
+          width: 18px;
+          height: 18px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          margin-right: 10px;
+          background-image: url("../../../assets/img/edit_u.png");
+        }
+        .chapter_upload_ic_r {
+          width: 18px;
+          height: 18px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          background-image: url("../../../assets/img/delete_u.png");
+        }
+      }
+    }
+  }
+  .masking-out {
+    width: 100px;
+    height: 135px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    display: none;
+    border-radius: 5%;
+    background: #00000053;
+    .delete {
+      cursor: pointer;
+      margin-left: 50%;
+      margin-top: 50%;
+      transform: translate(-50%, -50%);
+    }
+    .delete:hover {
+      color: #fff;
+    }
+  }
+  .fileBlock:hover .masking-out {
+    display: block;
+  }
+}
 </style>

+ 367 - 2
src/views/projectSettlement/components/studentProjectWordShowNew.vue

@@ -180,6 +180,36 @@
               <span v-html="downWordData.introduce.plan"></span>
             </td>
           </tr>
+					<tr>
+        <td class="bold">附件上传</td>
+      	  <td
+      	    colspan="6"
+      	    class="textLeft"
+      	    style="height: 200px; position: relative"
+      	  >
+      	    <!-- <el-button type="primary" style="position: absolute; right: 130px; top: 5px" v-if="![1,2].includes($store.state.userInfo.type) && wordData.courseId" @click="$emit('saveFile')">保存</el-button> -->
+      	    <div
+      	      v-if="downWordData.attachment"
+      	      :class="downWordData.attachment.length > 0 ? 'bigBlock' : 'noFileBox'"
+      	    >
+      	      <div
+      	        class="fileBlock"
+      	        v-for="(item, index) in downWordData.attachment"
+      	        :key="index + 'l'"
+      	      >
+      	        <div class="fileBox">
+      	          <div
+      	            class="fileBoxLeft"
+      	            @click="checkFile(item.url)"
+      	          >
+      	            <div class="chapter_upload_l_i3"></div>
+      	            <div class="titName">{{ item.fileName }}</div>
+      	          </div>
+      	        </div>
+      	      </div>
+      	    </div>
+      	  </td>
+      	</tr>
           <tr id="fund">
             <td rowspan="12" ref="fund">预算经费</td><td>总经费</td><td colspan="5" v-text="reversedMessage==0?'':reversedMessage"></td>
           </tr>
@@ -266,14 +296,62 @@
             <span>2.优先支持项目需提供与研发项目相关的实证材料并查看原件。</span>
           </div>
         </table>
+				<el-dialog
+				title="展示文件"
+				:visible.sync="showFile"
+				top="1vh"
+				width="80vw"
+				append-to-body
+				>
+				<div class="showFileArea" style="height: 80vh">
+				<!-- <vpdf v-if="/^\s*$/g.test(showFileUrl)&&showFileUrl.split('.')[showFileUrl.split('.').length-1]=='pdf'" :pdfUrl="showFileUrl"></vpdf> -->
+				<div
+					class="workd_media"
+					style="width: 90%; height: 90%"
+					v-if="videoDetail.sources"
+				>
+					<video-player
+						class="video-player vjs-custom-skin"
+						:playsinline="true"
+						:options="videoDetail"
+						@play="onPlayerPlay($event)"
+						style="width: 90%; height: 90%; margin: 0 auto"
+					></video-player>
+				</div>
+				<vword
+					style="width: 100%; height: 100%; overflow: auto"
+					class="fullStyle"
+					v-else-if="Wordss['type'] != 'pdf' && Wordss['name'] != '图片'"
+					:pdfUrl="
+						'https://view.officeapps.live.com/op/view.aspx?src=' + showFileUrl
+					"
+				></vword>
+				<vpdf
+					style="width: 100%; height: 100%; overflow: auto"
+					class="fullStyle"
+					:pdfUrl="showFileUrl"
+					v-else-if="Wordss['type'] == 'pdf'"
+				></vpdf>
+				<img
+					:src="showFileUrl"
+					alt="图片哦"
+					v-else-if="Wordss['name'] == '图片'"
+					style="width: auto; height: auto; max-width: 100%; max-height: 100%"
+				/>
+				</div>
+				<!-- <el-button type="primary" size="mini" @click="downFile(showFileUrl)">下载文件</el-button> -->
+				</el-dialog>
          
           <!-- <el-button style="margin-top:20px" type="primary" @click="work">下载表格</el-button> -->
     </div>
     </template>
       
     <script>
+		import vpdf from "@/components/vpdf.vue";
+			import vword from "@/components/vword.vue";
       // import {getWord} from '@/components/tool/getWord'
       export default {
+				components:{vpdf,vword},
         data() {
           return {
               downWordData:{
@@ -327,6 +405,110 @@
                 }
               },
               loading:false,
+							word: [
+      				  "DOC",
+      				  "DOCX",
+      				  "DOCM",
+      				  "DOTM",
+      				  "DOTX",
+      				  "PPTX",
+      				  "PPSX",
+      				  "PPT",
+      				  "PPS",
+      				  "PPTM",
+      				  "POTM",
+      				  "PPAM",
+      				  "POTX",
+      				  "PPSM",
+      				  "XLSX",
+      				  "XLS",
+      				],
+      				pdf: ["PDF"],
+      				image: [
+      				  "BMP",
+      				  "PJP",
+      				  "APNG",
+      				  "PNG",
+      				  "JPG",
+      				  "GIF",
+      				  "SVG",
+      				  "JPEG",
+      				  "JPG",
+      				  "ICO",
+      				  "PGPEG",
+      				  "AVIF",
+      				],
+      				vedio: [
+      				  "AVI",
+      				  "NAVI",
+      				  "MPEG",
+      				  "ASF",
+      				  "MOV",
+      				  "WMV",
+      				  "3GP",
+      				  "RM",
+      				  "RMVB",
+      				  "FLV",
+      				  "F4V",
+      				  "H.264",
+      				  "H.265",
+      				  "REAL VIDEO",
+      				  "MKV",
+      				  "WebM",
+      				  "HDDVD",
+      				  "MP4",
+      				  "MPG",
+      				  "M4V",
+      				  "MGV",
+      				  "OGV",
+      				  "QTM",
+      				  "STR",
+      				  "AMC",
+      				  "DVX",
+      				  "EVO",
+      				  "DAT",
+      				  "OGG",
+      				  "OGM",
+      				],
+      				playerOptions: {
+      				  playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
+      				  autoplay: false, //如果true,浏览器准备好时开始回放。
+      				  muted: false, // 默认情况下将会消除任何音频。
+      				  loop: false, // 导致视频一结束就重新开始。
+      				  preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+      				  language: "zh-CN",
+      				  aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+      				  fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+      				  sources: [
+      				    {
+      				      type: "video/mp4", //这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目   || "video/ogg"|| "video/webm"
+      				      src: "", //url地址require("../../assets/media/aaa.mp4")
+      				    },
+      				  ],
+      				  // poster: require("../../assets/tu31.png"), //你的封面地址
+      				  // poster: dataRes.imgUrl, //你的封面地址
+      				  notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
+      				  controlBar: {
+      				    timeDivider: true, //当前时间和持续时间的分隔符
+      				    durationDisplay: true, //显示持续时间
+      				    remainingTimeDisplay: false, //是否显示剩余时间功能
+      				    fullscreenToggle: true, //全屏按钮
+      				  },
+      				},
+      				playerO: {},
+      				videoDetail: {},
+							Wordss:{},
+							showFileUrl:"",
+							showFile:false,
+							canonical: {
+      				  Image:
+      				    /^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i,
+      				  File: /^https?:\/\/(.+\/)+.+(\.(docx|xlsx|ppt|pdf))$/i,
+      				},
+							updateFile:{
+								url:"",
+								fileName:""
+							},
             }
         },
         methods: {
@@ -362,12 +544,58 @@
                   wordData.brief=data.brief;
                   wordData.introduce=JSON.parse(data.chapters)
                   wordData.fund=JSON.parse(data.money)
+									wordData.attachment = data.attachment?JSON.parse(data.attachment):[]
                   this.downWordData={...wordData,...{etime:data.eTime,btime:data.bTime,dp:data.className}}
 									this.loading = false;
               },err=>{
                   console.log(err);
               })
           },
+					//展示文件
+		checkFile(url) {
+    			  this.videoDetail = {};
+    			  if (
+    			    this.vedio.indexOf(
+    			      url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			    ) != -1
+    			  ) {
+    			    this.playerOptions.sources[0].src = url;
+    			    this.videoDetail = this.playerOptions;
+    			    this.showFile = true;
+    			  } else {
+    			    if (
+    			      this.word.indexOf(
+    			        url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			      ) == -1 &&
+    			      this.pdf.indexOf(
+    			        url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			      ) == -1 &&
+    			      this.image.indexOf(
+    			        url.split(".")[url.split(".").length - 1].toLocaleUpperCase()
+    			      ) == -1
+    			    ) {
+    			      this.downFile(url);
+    			      return;
+    			    }
+    			    this.showFileUrl = url;
+    			    this.showFile = true;
+    			    if (typeof url == "undefined") return { type: "", name: "" };
+    			    let urlSplit = url.split(".");
+    			    const type = urlSplit[urlSplit.length - 1];
+    			    if (this.canonical.Image.test(url)) {
+    			      this.Wordss = { type: type, name: "图片" };
+    			      return console.log(this.Wordss);
+    			    }
+    			    if (this.canonical.File.test(url)) {
+    			      this.Wordss = { type: type, name: "文档" };
+    			      return console.log(this.Wordss);
+    			    }
+    			    if (this.canonical.vedio.test(url)) {
+    			      this.Wordss = { type: type, name: "视频" };
+    			      return console.log(this.Wordss);
+    			    } else return (this.Wordss = { type: type, name: type });
+    			  }
+    },
         },
         computed:{   //经费总合
           reversedMessage: function () {
@@ -381,7 +609,8 @@
         },
 				activated(){
 					this.getData();
-				}
+				},
+				
       };
     </script>
       
@@ -514,5 +743,141 @@
         }
 
       }
-    
+			.noFileBox {
+  width: 98%;
+  min-height: 200px;
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+}
+.bigBlock {
+  width: 98%;
+  min-height: 200px;
+  display: flex;
+  flex-direction: column;
+  flex-wrap: nowrap;
+  align-items: flex-start;
+  border: 1px solid #cad1dc;
+  border-radius: 4px;
+  padding: 10px;
+  .fileBlock {
+    width: 98%;
+    margin-right: 20px;
+    position: relative;
+    border-radius: 5%;
+    padding: 5px 0 5px 0;
+    border-bottom: 1px solid #cad1dc;
+    .fileBox {
+      display: flex;
+      flex-direction: row;
+      flex-wrap: nowrap;
+      justify-content: space-between;
+      align-items: center;
+
+      .fileBoxLeft {
+        cursor: pointer;
+        display: flex;
+        flex-direction: row;
+        flex-wrap: nowrap;
+        align-items: center;
+        .chapter_upload_l_i3 {
+          width: 15px;
+          height: 15px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          background-image: url("../../../assets/img/u_video.png");
+        }
+        .titName {
+          width: calc(100% - 15px);
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          word-break: break-word;
+          text-align: left;
+          margin-left: 10px;
+          max-width: 800px;
+        }
+      }
+      .fileBoxRight {
+        cursor: pointer;
+        display: flex;
+        flex-direction: row;
+        flex-wrap: nowrap;
+        align-items: center;
+        .chapter_upload_ud {
+          display: flex;
+          flex-direction: row;
+          justify-content: center;
+          margin: 0 10px 0 0;
+          .chapter_upload_up {
+            margin-right: 10px !important;
+          }
+          .chapter_upload_down,
+          .chapter_upload_up {
+            width: 20px;
+            height: 20px;
+            background: #e4eaf2;
+            cursor: pointer;
+            margin: 0 auto;
+            border-radius: 5px;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+          }
+        }
+        .chapter_upload_up::after,
+        .chapter_upload_down::after {
+          content: "";
+          background-image: url("../../../assets/img/downBtn.png");
+          width: 13px;
+          height: 13px;
+          background-size: 100% 100%;
+          display: block;
+        }
+
+        .chapter_upload_up::after {
+          background-image: url("../../../assets/img/upBtn.png") !important;
+        }
+        .chapter_upload_ic_edit {
+          width: 18px;
+          height: 18px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          margin-right: 10px;
+          background-image: url("../../../assets/img/edit_u.png");
+        }
+        .chapter_upload_ic_r {
+          width: 18px;
+          height: 18px;
+          background-repeat: no-repeat;
+          background-size: 100% 100%;
+          background-image: url("../../../assets/img/delete_u.png");
+        }
+      }
+    }
+  }
+  .masking-out {
+    width: 100px;
+    height: 135px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    display: none;
+    border-radius: 5%;
+    background: #00000053;
+    .delete {
+      cursor: pointer;
+      margin-left: 50%;
+      margin-top: 50%;
+      transform: translate(-50%, -50%);
+    }
+    .delete:hover {
+      color: #fff;
+    }
+  }
+  .fileBlock:hover .masking-out {
+    display: block;
+  }
+}
     </style>

+ 2 - 0
src/views/resultShow/components/resultDetail_MakerSpace.vue

@@ -680,10 +680,12 @@ export default {
           this.TitleMessage["teacher"] = JSON.parse(
             this.TitleMessage["teacher"]
           );
+					this.TitleMessage["teacher"] = this.TitleMessage["teacher"].filter(i=>i.name!='')
           // 学生表格
           this.TitleMessage["student"] = JSON.parse(
             this.TitleMessage["student"]
           );
+					this.TitleMessage["student"] = this.TitleMessage["student"].filter(i=>i.name!='')
           //项目详细
           this.DetailMessage = JSON.parse(FormData[1][0]["chapters"]);
           // //项目附件

+ 2 - 0
src/views/resultShow/components/resultDetail_student.vue

@@ -805,10 +805,12 @@ export default {
           this.TitleMessage["teacher"] = JSON.parse(
             this.TitleMessage["teacher"]
           );
+					this.TitleMessage["teacher"] = this.TitleMessage["teacher"].filter(i=>i.name!='')
           // 学生表格
           this.TitleMessage["student"] = JSON.parse(
             this.TitleMessage["student"]
           );
+					this.TitleMessage["student"] = this.TitleMessage["student"].filter(i=>i.name!='')
           this.TitleMessage["multiSelectProject"] = JSON.parse(
             this.TitleMessage["multiSelectProject"]
           );