Explorar o código

Merge branch 'develop' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop

CrazyIter_Bin hai 1 ano
pai
achega
e071fe53df

+ 18 - 12
TEAMModelBI/ClientApp/src/view/userInquire/details.vue

@@ -39,7 +39,7 @@
                 <el-image :src="randomImage" fit="contain" v-else/>
             </div>
             <div class="topbox-name">
-                <div class="topbox-name-text">{{usernames}}</div>
+                <div class="topbox-name-text">{{usernames ? usernames :'暂无姓名'}} </div>
                 <div class="topbox-name-advance" @click="userdetailState=true">查看账户进阶数据<el-icon><MoreFilled /></el-icon></div>
             </div>
            </div>
@@ -49,7 +49,7 @@
                   <use :xlink:href="item.icon"></use>
                 </svg>
                 <span class="information-text">{{item.value}}</span>
-                <div :title="[item.correlation ? '已关联':'弱关联,可进行手动修改']" v-show="item.key ==='school'">
+                <div :title="[item.correlation ? '已关联':'弱关联,可进行手动修改']" v-show="item.key ==='school' && item.value !=='无'">
                     <svg class="hint-icon" aria-hidden="true"  >
                         <use :xlink:href="[item.correlation ? '#icon-zhengque3':'#icon-tishi2']"></use>
                     </svg>
@@ -228,7 +228,7 @@
                                                 <span class="rightsbox-item-time-num">{{item.startDateText}}~{{item.endDateText}}</span>
                                                 <span>共<span class="rightsbox-item-timenums">{{item.intervalTime}}</span>天</span>
                                             </p>
-                                            <p  v-if="item.aprule.hasOwnProperty('schoolinfo')">
+                                            <p  v-if=" item.aprule &&item.aprule.hasOwnProperty('schoolinfo') ">
                                                 <span>学校:</span>
                                                 <span class="rightsbox-item-timenums">{{item.aprule.schoolinfo.name}}</span>
                                             </p>
@@ -352,7 +352,7 @@
                     <div class="logintotal-box-table">
                         <p class="logintotal-box-table-title">登入详细:</p>
                         <el-table :data="logintotalTable" style="width: 100%" height="35vh" border >
-                            <el-table-column prop="product" label="平台" align="center"/>
+                            <el-table-column prop="nameText" label="平台" align="center"/>
                             <el-table-column prop="timeText" label="时间" align="center"/>
                         </el-table>
                     </div>
@@ -404,8 +404,9 @@ let productdata = ref([
     { id: 3, title: 'IES', value:0,valueText:'',key:'IES5', state: false },
     { id: 4, title: '苏格拉底', value:0,valueText:'',key:'Sokrates', state: false },
     { id: 5, title: '觀議課 APP', value:0,valueText:'',key:'SokAPP', state: false },
-    { id: 6, title: '通用账号', value:0,valueText:'',key:'Account ', state: false },
-    { id: 7, title: 'WebIRS5', value:0,valueText:'',key:'IRS', state: false },
+    { id: 6, title: '通用账号', value:0,valueText:'',key:'Account', state: false },
+    { id: 7, title: 'HiTeachCC', value:0,valueText:'',key:'HiTeachCC', state: false },
+    { id: 8, title: 'WebIRS5', value:0,valueText:'',key:'IRS', state: false },
 ])
 let tableData = ref([
     { time: '2023-07-05 15:33', ip: '222.209.14.199', location: '四川省成都市',platform:'HiTeach' },
@@ -754,12 +755,12 @@ function initdata() {
     let { name,id,mobile, mail, schoolCode, schoolCodeW, points,country,province,city,picture} = transmitData
     userPortrait.value=picture
     usernames.value=name
-    userdata.value[0].value = id
-    userdata.value[1].value = mobile
+    userdata.value[0].value = id ? id:'暂无'
+    userdata.value[1].value = mobile ?mobile:'暂无'
     userdata.value[2].value = schoolCodeW ? schoolCodeW : schoolCode ? schoolCode:'无'
     schoolCodeW ? userdata.value[2].correlation=true:false
-    userdata.value[3].value = mail
-    userdata.value[4].value = country && province && city ? country+'-'+province+city:country+'-'+province
+    userdata.value[3].value = mail ? mail:'暂无'
+    userdata.value[4].value = country && province && city ? country+'-'+province+city:country && province ? country+'-'+province:'暂无'
     //产品使用及安装情况 登入时间
     let {login}=transmitData
     let logintimes = login.length >0 ? login.sort(function(a,b){return b.time-a.time}):'无'
@@ -775,7 +776,8 @@ function initdata() {
             typename === items.key ? 
             items.value === 0 ? (items.valueText=proxy.$common.timestampToTime(item.time,'all'),items.value=item.time,items.state=true): 
             item.time > items.value ? (items.valueText=proxy.$common.timestampToTime(item.time,'all'),items.value=item.time,items.state=true):'':''
-         })
+            typename === items.key ? item.nameText=items.title:''
+        })
          item.timeText=proxy.$common.timestampToTime(item.time,'all')
          logintotalTable.value.push(item)
        })
@@ -785,6 +787,7 @@ function initdata() {
             item.state=false
         })
     }
+    console.log(logintotalTable.value,'数据~')
     //空间与权益
     let {usedSize,teachSize,totalSize,surplusSize}=transmitData.ies5
     let usePercentum=parseInt(((Number(bytesToGB(usedSize))+Number(bytesToGB(teachSize)))/Number(bytesToGB(totalSize)))*100);let useGsize=proxy.$common.convertSize(usedSize)
@@ -810,7 +813,7 @@ function initdata() {
             apruleItem.cloudas ? powerExtension.value[9].state=true:powerExtension.value[9].state=false  //雲端診斷分析系統
             apruleItem.cligroup !==0 ? (powerExtension.value[10].state=true,powerExtension.value[10].value=apruleItem.cligroup):powerExtension.value[10].state=false //分組數
             apruleItem.client_volume !==0 ? (powerExtension.value[11].state=true,powerExtension.value[11].value=apruleItem.client_volume):powerExtension.value[11].state=false  //IRS連線授權數
-            apruleItem.soknumber !==0 ? (powerExtension.value[12].state=true,powerExtension.value[10].value=apruleItem.soknumber):powerExtension.value[12].state=false //議課人數
+            apruleItem.soknumber !==0 ? (powerExtension.value[12].state=true,powerExtension.value[12].value=apruleItem.soknumber):powerExtension.value[12].state=false //議課人數
             apruleItem.scorsys ? (powerExtension.value[13].state=true,powerExtension.value[13].value=apruleItem.soknumber):powerExtension.value[13].state=false //智慧評分系統
             apruleItem.hasOwnProperty('irs') ? powerExtension.value[14].state=false:powerExtension.value[14].state=true  //IRS硬體遙控器
             item.apruleArr=powerExtension.value
@@ -1103,6 +1106,9 @@ watch(()=>transferNum.value,(newnum)=>{
 .Account{
     background: linear-gradient(to top right, #FAACA8, #DDD6F3); 
 }
+.HiTeachCC{
+    background: linear-gradient(to top right, #74EBD5, #9FACE6); 
+}
 
 .notenabled{
     background-color: #dcdaef;

+ 15 - 1
TEAMModelBI/ClientApp/src/view/userInquire/ies.vue

@@ -13,7 +13,7 @@
         </div>
         <el-divider />
             <div class="joinSchool">
-                <div class="joinSchool-item">
+                <div class="joinSchool-item" v-if="iesShow">
                     <div class="joinSchool-img">
                         <svg class="joinSchool-icon" aria-hidden="true">
                             <use xlink:href="#icon-xuexiao8"></use>
@@ -62,6 +62,9 @@
                         <span>默认学校</span>
                     </div>
                 </div>
+                <div class="not-datas" v-else>
+                    暂无学校信息
+                </div>
             </div>
         <el-divider />
             <div class="ies-flex">
@@ -148,6 +151,7 @@
       {name:'南京特殊教育师范学院',code:'ntsjsy',location:'中国',class:15,totalsize:300,occupy:75}
  ])
  let allschoolList=ref([])
+ let iesShow=ref(true)
  let echartsBar=ref({
     tooltip: {
         trigger: 'axis',
@@ -254,6 +258,10 @@
  })
  function initdatas(){
     console.log(props.iesdata,'IESde zhi')
+    if(!props.iesdata){
+        iesShow.value=false 
+        return
+    }
     let {resCount,itemCount,paperCount}=props.iesdata
     relevancedata.value[0].value=resCount
     relevancedata.value[1].value=itemCount
@@ -546,6 +554,12 @@ watch(()=>props,(newvalue)=>{
  .fontsize{
     font-size:12px;
  }
+ .not-datas{
+    font-size:16px;
+    font-weight: 700;
+    color: #73767a;
+    line-height: 40px;
+}
  </style>
 <style>
 .dialog-school .el-dialog__body{

+ 33 - 12
TEAMModelBI/ClientApp/src/view/userInquire/socrates.vue

@@ -30,7 +30,7 @@
         <!-- <div class="socrates-echatrs">
             <bars :barData="ecahrtsdata"></bars>
         </div> -->
-        <div class="tnum-content">
+        <div class="tnum-content"  v-if="sokratesEchart">
                 <div class="selectbox">
                     <div><el-button v-for="item in buttonSelect" :key="item.value" :type="item.click ? 'primary':''" size="small" class="clickbox" @click="selectTime(item.value)">{{item.name}}</el-button></div>
                     <div class="nowaday-time">时间:<span class="time-values">{{hiteachDatas.appear.start_date}}~{{hiteachDatas.appear.end_date}}</span></div>
@@ -61,7 +61,10 @@
                         </div>
                     </div>
                 </div>
-            </div>
+        </div>
+        <div class="tnum-content" v-else>
+            <div class="not-coupons">暂无数据</div>
+        </div>
     </div>
  </template>
  <script setup>
@@ -361,6 +364,7 @@ let proportiondata = ref({
         },
     ]
 })
+let sokratesEchart=ref(true)
 let zb = ref()
 onMounted(() => {
     initdatas()
@@ -381,20 +385,23 @@ function initdatas(){
         presupposed.value.state=false
     }
     //处理total数据
-    primary.value[0].value=hiteach_data.total.t_data ? hiteach_data.total.t_data:0
-    primary.value[1].value=hiteach_data.total.t_green ? hiteach_data.total.t_green:0
-    primary.value[2].value=hiteach_data.total.double_green_light ? hiteach_data.total.double_green_light:0
-    primary.value[3].value=hiteach_data.total.all_total ?  hiteach_data.total.all_total:0
+    primary.value[0].value=hiteach_data && hiteach_data.total.t_data ? hiteach_data.total.t_data:0
+    primary.value[1].value=hiteach_data && hiteach_data.total.t_green ? hiteach_data.total.t_green:0
+    primary.value[2].value=hiteach_data && hiteach_data.total.double_green_light ? hiteach_data.total.double_green_light:0
+    primary.value[3].value=hiteach_data && hiteach_data.total.all_total ?  hiteach_data.total.all_total:0
 
     auxiliary.value[0].value='XXX'
-    auxiliary.value[1].value=hiteach_data.total.personal_comment ? hiteach_data.total.personal_comment:0
-    auxiliary.value[2].value=hiteach_data.total.watchHistory ?  hiteach_data.total.watchHistory:0
+    auxiliary.value[1].value=hiteach_data&& hiteach_data.total.personal_comment ? hiteach_data.total.personal_comment:0
+    auxiliary.value[2].value=hiteach_data && hiteach_data.total.watchHistory ?  hiteach_data.total.watchHistory:0
     auxiliary.value[3].value='XXX'
+    if(!hiteach_data){
+        sokratesEchart.value=false
+    }
     //处理下方图表
-    hiteachDatas.value.weeks=hiteach_data.this_week
-    hiteachDatas.value.months=hiteach_data.this_month
-    hiteachDatas.value.years=hiteach_data.this_year
-    hiteachDatas.value.appear=hiteach_data.this_week
+    hiteachDatas.value.weeks=hiteach_data && hiteach_data.this_week ? hiteach_data.this_week:0
+    hiteachDatas.value.months= hiteach_data && hiteach_data.this_month ?hiteach_data.this_month:0
+    hiteachDatas.value.years= hiteach_data && hiteach_data.this_year ?hiteach_data.this_year:0
+    hiteachDatas.value.appear=hiteach_data && hiteach_data.this_week ?hiteach_data.this_week:0
     tdatas.value[0].values=hiteachDatas.value.appear.duration
     tdatas.value[1].values=hiteachDatas.value.appear.attendance
     tdatas.value[2].values=hiteachDatas.value.appear.interaction
@@ -403,6 +410,10 @@ function initdatas(){
 }
 function selectTime(values) {
     console.log(values)
+    if(!props.sokratesdatas.hiteach_data){
+        sokratesEchart.value=false
+        return
+    }
     let hiteach_data=props.sokratesdatas.hiteach_data
     values === 'week' ?  hiteachDatas.value.appear=hiteach_data.this_week:values === 'month' ? hiteachDatas.value.appear=hiteach_data.this_month:
     values === 'year' ? hiteachDatas.value.appear=hiteach_data.this_year:values ==='total' ? hiteachDatas.value.appear=hiteach_data.total:''
@@ -571,4 +582,14 @@ watch(()=>props,(newvalue)=>{
 .time-values,.content-num{
     color:#409EFF !important;
 }
+.not-coupons{
+    display: flex;
+    height:90%;
+    align-items: center;
+    justify-content: center;
+    font-size:22px;
+    font-weight: 700;
+    color: #73767a;
+    /* line-height: 160px; */
+}
 </style>

+ 26 - 24
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -3429,7 +3429,7 @@ const LANG_EN_US = {
         apiError: {
             text1: ' User name or password incorrect',
             text2: 'You have graduated and cannot log in at this time!',
-            text3: 'Binding failed. This account has already been linked to the Taiwan Education Cloud.',
+            text3: 'Binding failed. This account has already been bound to a Taiwan Education Cloud account.',
         },
         sse: {
             error: {
@@ -3456,13 +3456,13 @@ const LANG_EN_US = {
             }
         },
         bindEDUModal: {
-            title: 'Connect to the Taiwan Education Cloud',
+            title: 'Bind to the Taiwan Education Cloud',
             tab1: {
-                title: 'I have a TEAM Model account, Link/bind below.',
+                title: 'I already have a TEAM Model account, Link/bind below.',
                 btn: 'Bind',
                 err: {
-                    text1: 'Account/password cannot be empty.',
-                    text2: 'Account/password is incorrect.'
+                    text1: 'Account or password cannot be empty.',
+                    text2: 'Account or password is incorrect.'
                 }
             },
             tab2: {
@@ -3471,18 +3471,20 @@ const LANG_EN_US = {
                 btn: 'Login',
                 doubleCheckModal: {
                     title: 'Log in directly',
-                    cont: 'Are you sure you want to create a TEAM Model account through the Taiwan Education Cloud ?',
+                    cont: 'Are you sure you want to create a TEAM Model account through the Taiwan Education Cloud?',
                     okText: 'OK',
                     cancelText: 'Cancel'
                 },
             },
-            no: "Seat Number",
+            seatNo: 'Seat No.',
+            classroomName: 'Class Name',
+            grade: 'Grade',
             error: {
                 text1: 'Sorry, your school currently does not support this service.',
-                text2: 'You have graduated from school.',
+                text2: 'You have graduated from the school.',
                 text3: 'The school does not have your information.',
                 text4: 'This student has already been linked to the Taiwan Education Cloud.',
-                text5: 'You are not assigned to a class.',
+                text5: 'You are not been assigned to a class.',
             }
         },
         china: 'China ',
@@ -3728,8 +3730,8 @@ const LANG_EN_US = {
             studentDash: 'Student Dashboard',
             dashTitle: 'Select the data dashboard to view',
             schoolSummary: 'Showcases school information, teaching resources, and course dynamics, providing an overview of the school for school leaders',
-            teacherSummary: "Displays smart classroom data, focusing on teaching and learning outcomes to support students' comprehensive development",
-            studentSummary: 'Displays students holistic development in virtues, intelligence, physical fitness, aesthetics, and labor, promoting a positive school culture and nurturing well-rounded personalities',
+            teacherSummary: "Displays smart lesson data, focusing on teaching and learning outcomes to support student comprehensive development",
+            studentSummary: 'Displays students holistic development in virtues, intelligence, physique, social skills, and aesthetics, promoting a positive school culture and nurturing well-rounded personalities',
             cols: 'Display Columns',
             title: 'Smart Campus Big Data',
             title3: 'All-round Quality Big Data',
@@ -4637,10 +4639,10 @@ const LANG_EN_US = {
             survey: "Survey",
             wrongTopic: "Question Book",
             wrongTopic1: "SMART Practice",
-            wrongTopic2: "Incorrectly Answered Qs",
+            wrongTopic2: "Question Book",
             classInteraction: "Web IRS",
             achievement: "Grade",
-            discussionBoard: 'Discussion Board',
+            discussionBoard: 'Discussion',
         },
         testType: [{
             label: "Single Answer",
@@ -5111,7 +5113,7 @@ const LANG_EN_US = {
                 next: 'Next Question',
                 myAnswerSheet: 'My Answer Card',
                 exitQuizhint: 'Reminder',
-                exitQuizhintD: "If you leave the page, you answered data will not be saved, are you sure to leave?",
+                exitQuizhintD: "If you leave the page, your answered data will not be saved, are you sure to leave?",
                 exitQuizhintD1: "If you leave the page, the system will acknowledge that you have submitted answer by default, and you cannot answer again. Are you sure to leave?",
                 exitQuizhintDe: 'The system has detected that you have not yet "submit your answers", if you choose "OK",',
                 exitQuizhintDes: 'the current answer will not be saved, and the assessment will need to be retaken next time.',
@@ -5366,16 +5368,16 @@ const LANG_EN_US = {
             headerTitle1: 'SMART Incorrectly Answered Question Practice',
             headerTitle2: 'Current Question',
             question1: 'Question Stem',
-            modalTitle1: 'Revisit Mistakes',
+            modalTitle1: 'Review Now',
             modalTitle2: 'Exit Practice',
             modal1: 'All current exercises have been completed and submitted. The practice results are as follows:',
             modal2: 'Time Used',
             modal3: 'There are a total of ',
-            modal4: 'questions that were answered incorrectly or not understood. Would you like to review these questions again? (Review only; no record will be kept)',
+            modal4: ' questions that were answered incorrectly or not understood. Would you like to review these questions again? (Review only and no record will be kept)',
             modal5: 'Congratulations! There were no incorrectly answered or misunderstood questions in this practice session. You can exit the practice now.',
-            stats1: 'Correct Answers',
-            stats2: 'Incorrect Answers',
-            showOptionType: 'Show Objective Options',
+            statistics1: 'Correctly Answered',
+            statistics2: 'Incorrectly Answered',
+            showOptionType: "Show Objective Question's Options",
         },
         informviewTitle: 'Notification Overview',
         view: 'Go to view',
@@ -5433,11 +5435,11 @@ const LANG_EN_US = {
             classmates: 'Classmates list',
             classmates1: 'TEAM Model List',
             classRecord: "Lesson Records",
-            examRecord: "Assessment List",
-            hwRecord: "Homework List",
-            voteRecord: "Poll Activity",
-            surRecord: "Survey Activity",
-            activityList: "Activity List",
+            examRecord: "Assessment",
+            hwRecord: "Homework",
+            voteRecord: "Poll",
+            surRecord: "Survey",
+            activityList: "Activity",
             classID: 'Course Code',
             classTime: 'Class Time',
             classroom: 'Classroom',

+ 3 - 1
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -3475,7 +3475,9 @@ const LANG_ZH_CN = {
                     cancelText: '取消'
                 },
             },
-            no: "座号",
+            seatNo: "座号",
+            grade: '年级',
+            classroomName: '班级名称',
             error: {
                 text1: '很抱歉,您的学校目前没有支持此服务。 ',
                 text2: '您已于学校毕业。 ',

+ 3 - 1
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -3478,7 +3478,9 @@ const LANG_ZH_TW = {
                     cancelText: '取消'
                 },
             },
-            no: "座號",
+            grade: "年級",
+            classroomName: "班級名稱",
+            seatNo: "座號",
             error: {
                 text1: '很抱歉,您的學校目前沒有支持此服務。',
                 text2: '您已於學校畢業。',

+ 2 - 1
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperViewBox/PaperTest.vue

@@ -279,7 +279,7 @@
                                             :disabled="!closeTest" />
                                         <div class="testbg">
                                             <div style="display:flex">
-                                                <span>{{ getQue(queNo).option[index].code }}.</span>
+                                                <span>{{ getQue(queNo).option[index].code }}. </span>
                                                 <div v-html="item.value" @click.stop="showImg($event)"></div>
                                             </div>
                                             <div style="clear:both"></div>
@@ -482,6 +482,7 @@
             if(artExam === 1 && !this.$tools.isMobile()) {
                 const full = document.getElementById("full")
                 full.requestFullscreen()
+                // 2023.11.20 #2987 C528 Edge浏览器的clientHeight < screen.height ,导致加入作答页面就提示退出全屏,待处理
                 window.addEventListener('resize', function () {
                     // 根据可视高度判断是否退出全屏
                     const clientHeight = document.documentElement.clientHeight || document.body.clientHeight

+ 14 - 5
TEAMModelOS/ClientApp/src/view/login/Index.vue

@@ -43,8 +43,8 @@
           overflow-y: auto;
         }
         .stud{
-          width: 130px;
-          padding: 5px 9px;
+          min-width: 130px;
+          padding: 6px 15px;
           border-radius: 5px;
           margin-bottom: 5px;
           margin-right: 5px;
@@ -53,6 +53,15 @@
           cursor: pointer;
           background-color: #EEEEEE;
           font-size: 14px;
+          .grade{
+            text-align: left;
+          }
+          .class{
+            text-align: left;
+          }
+          .no{
+            text-align: left;
+          }
           &.select{
             border: 2px solid rgb(99, 116, 145);
             font-weight: bold;
@@ -578,9 +587,9 @@
             <div class="bindEDUModal-form-studs" :class="{'center': bindStuds.length == 1}">
               <div class="stud" v-for="bindStud in bindStuds" :class="{'select': bindStudForm.stuid == bindStud.id}" @click="bindStudForm.stuid = bindStud.id">
                 <div class="period">{{bindStud.periodName}}</div>
-                <div class="grade">{{bindStud.gradeName}}</div>
-                <div class="class">{{bindStud.className}}</div>
-                <div class="no" v-if="bindStud.no">{{$t('login.bindEDUModal.no')}}: {{bindStud.no}}</div>
+                <div class="grade" v-if="bindStud.gradeName">{{$t('login.bindEDUModal.grade')}}: {{bindStud.gradeName}}</div>
+                <div class="class" v-if="bindStud.className">{{$t('login.bindEDUModal.classroomName')}}: {{bindStud.className}}</div>
+                <div class="no" v-if="bindStud.no">{{$t('login.bindEDUModal.seatNo')}}: {{bindStud.no}}</div>
               </div>
             </div>
           </FormItem>

+ 276 - 84
TEAMModelOS/ClientApp/src/view/signupActivity/createActivity.vue

@@ -23,7 +23,7 @@
                             <Input v-model="createData.address" placeholder="请输入活动地点"></Input>
                         </FormItem>
                         <FormItem label="时间">
-                            <DatePicker :editable="false" @on-change="getCreateTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" style="width: 500px"></DatePicker>
+                            <DatePicker v-model="actAllTime[0]" :editable="false" @on-change="getCreateTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" style="width: 500px"></DatePicker>
                         </FormItem>
                         <FormItem label="主办" class="unit-box">
                             <div v-for="(item, index) in createData.zb" :key="index">
@@ -102,7 +102,7 @@
                                 <div style="margin-top: 20px;">
                                     <div :key="index" v-for="(item, index) in attachment" class="uploadHm">
                                         <span style="float: right;margin-right: 55px;" v-show="!isUpload">
-                                            <Icon type="md-close" size="18" @click="delUpload(index)" />
+                                            <Icon type="md-close" size="18" @click="delUpload(index, item)" />
                                         </span>
                                         <div @click="changeUp(index)" style="width: 100%;">
                                             {{ item.name }}
@@ -127,7 +127,7 @@
                                         <div class="content-box">
                                             <div>
                                                 <FormItem label="报名时间">
-                                                    <DatePicker :editable="false" @on-change="getActTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" style="width: 500px"></DatePicker>
+                                                    <DatePicker v-model="actAllTime[1]" :editable="false" @on-change="getActTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" style="width: 500px"></DatePicker>
                                                 </FormItem>
                                                 <FormItem label="报名人数">
                                                     <InputNumber :min="0" v-model="contestData.sign.limit" />
@@ -138,11 +138,11 @@
                                                 </FormItem>
                                                 <FormItem label="填报信息">
                                                     <CheckboxGroup v-model="fields">
-                                                        <Checkbox v-for="(item, index) in infoArr" :key="index" :label="item.value">
+                                                        <Checkbox v-for="(item, index) in infoArr" :key="index" :label="item.field">
                                                             <span>
                                                                 {{ item.label }}
                                                                 <Icon type="md-create" size="18" color="orange" v-show="index > 4" @click.stop.native.prevent="changeFiled(2, item)" />
-                                                                <Icon type="md-trash" size="16" color="#6e6e6e" v-show="item.value === item.label" @click.stop.native.prevent="delField(index)" />
+                                                                <Icon type="md-trash" size="16" color="#6e6e6e" v-show="item.field === item.label" @click.stop.native.prevent="delField(index)" />
                                                             </span>
                                                         </Checkbox>
                                                         <Icon type="md-add-circle" @click="changeFiled(1)" size="18" />
@@ -163,7 +163,7 @@
                                             </p>
                                             <div v-show="skWork">
                                                 <FormItem label="上传时间">
-                                                    <DatePicker :editable="false" @on-change="getWorkTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" style="width: 500px"></DatePicker>
+                                                    <DatePicker v-model="actAllTime[2]" :editable="false" @on-change="getWorkTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" style="width: 500px"></DatePicker>
                                                 </FormItem>
                                                 <FormItem label="作品类型">
                                                     <RadioGroup v-model="contestUpload.type">
@@ -203,12 +203,13 @@
                                             </p>
                                             <div v-show="skReview">
                                                 <FormItem label="评审时间">
-                                                    <DatePicker :editable="false" @on-change="getReviewTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" transfer style="width: 500px"></DatePicker>
+                                                    <DatePicker v-model="actAllTime[3]" :editable="false" @on-change="getReviewTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" transfer style="width: 500px"></DatePicker>
                                                 </FormItem>
                                                 <FormItem label="评审规则">
                                                     <Select v-model="reviewSel" transfer style="width: calc(100% - 30px);">
                                                         <Option v-for="(item, index) in reviewList" :value="index" :key="index" class="review-sel">
                                                             {{ item.name }}
+                                                            <span v-show="item.currentUse" style="color: #2d870e;">({{ '当前活动使用' }})</span>
                                                             <Icon type="md-eye" size="18" color="#077fd8" @click.native="reviewEditRule(index, 'preview')" />
                                                             <Icon type="ios-copy" size="18" color="#5a5a5a" @click.native="reviewEditRule(index, 'copy')" v-show="!item.isAdd" />
                                                             <Icon type="md-create" size="18" color="orange" @click.native="reviewEditRule(index, 'edit')" v-show="item.isAdd" />
@@ -225,7 +226,7 @@
                                             </p>
                                             <div v-show="skPublic">
                                                 <FormItem label="公示时间">
-                                                    <DatePicker :editable="false" @on-change="getPublicTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" transfer style="width: 500px"></DatePicker>
+                                                    <DatePicker v-model="actAllTime[4]" :editable="false" @on-change="getPublicTime" type="datetimerange" format="yyyy-MM-dd HH:mm" :placeholder="$t('train.create.timeHolder')" transfer style="width: 500px"></DatePicker>
                                                 </FormItem>
                                             </div>
                                         </div>
@@ -247,7 +248,7 @@
                             <p>主题:{{ createData.subject }}</p>
                             <p>简介:{{ createData.description }}</p>
                             <p>地点:{{ createData.address }}</p>
-                            <p>时间:{{ createTime[0] }} - {{ createTime[1] }}</p>
+                            <p>时间:{{ actAllTime[0][0] }} - {{ actAllTime[0][1] }}</p>
                             <p>主办:
                                 <span v-for="(item, index) in createData.zb" :key="index" class="multiple-box">
                                     {{ item }}
@@ -279,7 +280,7 @@
                     </div>
                 </div>
                 <Button style="margin-top: 16px; margin-right: 16px;" @click="last" v-show="current">上一步</Button>
-                <Button style="margin-top: 16px;" type="primary" @click="next">{{ current === 2 ? '发布活动' : '下一步'}}</Button>
+                <Button style="margin-top: 16px;" type="primary" @click="nextNew">{{ current === 2 ? '发布活动' : '下一步'}}</Button>
             </vuescroll>
         </div>
         <Drawer title="评审规则" :width="50" :closable="false" v-model="ruleDrawer" class="light-iview-form" @on-close="closeRule()">
@@ -399,6 +400,7 @@
 
 <script>
 import BlobTool from "@/utils/blobTool.js"
+import { file } from 'jszip'
 export default {
     data() {
         let that = this
@@ -529,6 +531,8 @@ export default {
                 file: undefined,
             },
             attachment: [], //附件
+            attachDel: [], //编辑下删除原有的
+            attachAdd: [], //编辑下新增的
             createTime: [],
             createData: { // 活动基本信息
                 /* owner: '', //学校编码/区级id
@@ -550,6 +554,7 @@ export default {
                 attachment: [],
                 modules: [], //Contest/赛课活动 Training/线上培训 Research/教研活动 */
             },
+            actAllTime: [[], [], [], [], []],
             contestData: {
                 modules: ['sign'],
                 sign: {
@@ -637,7 +642,8 @@ export default {
             areaInfo: undefined,
         }
     },
-    created () {
+    async created () {
+        await this.initializeData()
         this.dataRuleMould = [{
             id: this.$tools.randomNum(10000, 99999) + '',
             label: '',
@@ -661,27 +667,6 @@ export default {
                 }]
             }]
         }]
-        this.createData = {
-            id: '',
-            owner: this.isArea ? this.areaId : this.$store.state.userInfo.schoolCode, //学校编码/区级id
-            ownerName: this.isArea ? sessionStorage.getItem('areaName') : this.$store.state.user.schoolProfile.school_base.name, //学校名称/学区名称
-            publish: 0, //发布状态 0未发布 1已发布 2已结束
-            name: '',
-            subject: '',
-            description: '',
-            address: '',
-            stime: '',
-            etime: '',
-            zb: [''], //主办方
-            cb: [''], //承办方
-            scope: this.isTMD ? 'public' : (this.isArea ? 'area' : 'school'), //public公开/area区级/school校级
-            invitedSchools: [], //邀请的学校列表
-            joinMode: 'enroll', //enroll/报名制 invite/邀请制
-            mzsm: '', //免责声明
-            poster: '',
-            attachment: [],
-            modules: [], //Contest/赛课活动 Training/线上培训 Research/教研活动
-        }
         this.ruleInfo = {
             name: '',
             desc: null,
@@ -704,6 +689,23 @@ export default {
         areaId() {
             return sessionStorage.getItem('areaId')
         },
+        isEdit() {
+            return !!this.$route.params.info
+        },
+        sasData() {
+            let info = {
+                url: this.$store.state.user.userProfile.blob_uri.split('/' + this.$store.state.userInfo.TEAMModelId)[0],
+                sas: ''
+            }
+            if(this.isArea) {
+                info.sas = this.$store.state.user.userProfile.areas.find(item => {
+                    return item.areaId === this.areaId
+                }).sas
+            } else {
+                info.sas = this.$store.state.user.schoolProfile.blob_sas
+            }
+            return info
+        },
     },
     watch: {
         'createData.scope': {
@@ -778,7 +780,110 @@ export default {
 
 
 
-
+        initializeData() {
+            return new Promise((r, j) => {
+                if(this.$route.params.info) {
+                    this.createData = this._.cloneDeep(this.$route.params.info)
+                    let contest = this._.cloneDeep(this.$route.params.contest)
+                    // 处理时间显示
+                    this.actAllTime[0].push(this.$tools.formatTime(this.createData.stime))
+                    this.actAllTime[0].push(this.$tools.formatTime(this.createData.etime))
+                    // 基本信息回显
+                    this.selSchools = this.createData.invitedSchools.map(item => {
+                        return item.id
+                    })
+                    this.posterFile = {
+                        url: this.createData.poster,
+                        file: undefined,
+                    }
+                    this.attachment = this._.cloneDeep(this.createData.attachment)
+                    this.initStatus(this.createData.modules)
+                    // 赛课模块回显
+                    this.contestData.modules = contest.modules
+                    this.contestData.sign = contest.sign
+                    this.actAllTime[1].push(this.$tools.formatTime(contest.sign.stime))
+                    this.actAllTime[1].push(this.$tools.formatTime(contest.sign.etime))
+                    this.contestData.sign.fields.forEach(item => {
+                        // 存在相同的字段,但类型不一致
+                        let sameField = this.infoArr.findIndex(infos => {return infos.field === item.field && infos.type != item.type})
+                        if(sameField != -1) {
+                            this.infoArr[sameField] = item
+                        }
+                        if(!this.infoArr.find(infos => {return infos.field === item.field})) {
+                            this.infoArr.push(item)
+                        }
+                        this.fields.push(item.field)
+                    })
+                    if(contest.modules.includes('upload')) {
+                        this.actAllTime[2].push(this.$tools.formatTime(contest.upload.stime))
+                        this.actAllTime[2].push(this.$tools.formatTime(contest.upload.etime))
+                        this.skWork = true
+                        this.contestUpload = contest.upload
+                        contest.upload.fileType.forEach(item => {
+                            this.fileType.forEach((file, index) => {
+                                if(file.format.includes(item)) {
+                                    file.isCheck = true
+                                    this.formatType[index].push(item)
+                                }
+                            })
+                        })
+                        this.formatType = this.formatType.map((item, index) => {
+                            item = item.length === this.fileType[index].format.length ? [] : item
+                            return item
+                        })
+                    }
+                    if(contest.modules.includes('review')) {
+                        this.actAllTime[3].push(this.$tools.formatTime(contest.review.stime))
+                        this.actAllTime[3].push(this.$tools.formatTime(contest.review.etime))
+                        this.skReview = true
+                        this.contestReview = contest.review
+                        this.reviewSel = this.reviewList.findIndex(item => {
+                            console.log(item.id, contest.review.ruleId);
+                            return item.id === contest.review.ruleId
+                        })
+                    }
+                    if(contest.modules.includes('score')) {
+                        this.actAllTime[4].push(this.$tools.formatTime(contest.score.stime))
+                        this.actAllTime[4].push(this.$tools.formatTime(contest.score.etime))
+                        this.skPublic = true
+                        this.contestScore = contest.score
+                    }
+                } else {
+                    this.createData = {
+                        id: '',
+                        owner: this.isArea ? this.areaId : this.$store.state.userInfo.schoolCode, //学校编码/区级id
+                        ownerName: this.isArea ? sessionStorage.getItem('areaName') : this.$store.state.user.schoolProfile.school_base.name, //学校名称/学区名称
+                        publish: 0, //发布状态 0未发布 1已发布 2已结束
+                        name: '',
+                        subject: '',
+                        description: '',
+                        address: '',
+                        stime: '',
+                        etime: '',
+                        zb: [''], //主办方
+                        cb: [''], //承办方
+                        scope: this.isTMD ? 'public' : (this.isArea ? 'area' : 'school'), //public公开/area区级/school校级
+                        invitedSchools: [], //邀请的学校列表
+                        joinMode: 'enroll', //enroll/报名制 invite/邀请制
+                        mzsm: '', //免责声明
+                        poster: '',
+                        attachment: [],
+                        modules: [], //Contest/赛课活动 Training/线上培训 Research/教研活动
+                    }
+                    this.contestData = {
+                        modules: ['sign'],
+                        sign: {
+                            fields: [], //填报信息
+                            stime: '',
+                            etime: '',
+                            limit: 0, //报名人数
+                            type: 0, //0个人 1团队
+                        },
+                    }
+                }
+                r(true)
+            })
+        },
         // 获取当前区级的权限
         getWebsite() {
             if(this.isArea) {
@@ -839,9 +944,20 @@ export default {
                 owner: this.isArea ? this.areaId : this.$store.state.userInfo.schoolCode
             }
             this.$api.areaActivity.manageAct(params).then(res => {
-                console.log(res);
                 if(res.reviewRules) {
                     this.reviewList = res.reviewRules
+                    if(this.isEdit && this.contestData.modules.includes('review')) {
+                        this.skReview = true
+                        this.reviewSel = this.reviewList.findIndex(item => {
+                            return item.id === this.contestReview.ruleId
+                        })
+                        // 使用的本次活动保存的规则,需要重新加入reviewList
+                        if(this.reviewSel === -1) {
+                            this.$route.params.reviewRule.currentUse = true
+                            this.reviewList.push(this.$route.params.reviewRule)
+                            this.reviewSel = this.reviewList.length - 1
+                        }
+                    }
                 }
             })
         },
@@ -854,12 +970,16 @@ export default {
                 params.Contest = this.contestData
                 this.contestData.modules.forEach(item => {
                     if(item === 'upload') {
+                        this.contestUpload.fileType = []
                         this.fileType.forEach((item, index) => {
                             if(item.isCheck) {
+                                console.log(this.contestUpload.fileType);
                                 if(this.formatType[index].length) {
                                     this.contestUpload.fileType = this.contestUpload.fileType.concat(this.formatType[index])
+                                    console.log(this.formatType[index]);
                                 } else {
                                     this.contestUpload.fileType = this.contestUpload.fileType.concat(item.format)
+                                    console.log(item.format);
                                 }
                             }
                         })
@@ -953,65 +1073,103 @@ export default {
                 })
             })
         },
-        async next() {
-            if(this.current === 2) {
-                // 在调用后端接口前进行以下操作:
-                // 1. 由前端创建本次活动的id
-                // this.createId = this.$tools.guid()
-                this.createData.id = this.$tools.guid()
-                // 2. 将封面、附件上传至blob,并填充createData中的poster attachment
-                let poster = await this.uploadBlob([this.posterFile.file])
-                let fjFile = await this.uploadBlob(this.attachment)
-                this.createData.poster = poster[0].url
-                this.createData.attachment = fjFile
-                this.createData.attachment.forEach(item => {
-                    item.hash = this.$tools.convertFileMD5ToString(item.md5)
-                    item.cnt = this.isArea ? this.areaId : this.$store.state.userInfo.schoolCode
-                })
-                // 3. 若有新创建的评审规则,需先保存,保存大活动时由后端一起保存
-                this.saveActivity()
-            } else {
-                this.createData.invitedSchools = []
-                this.contestData.sign.fields = []
-                this.showSchools.forEach(item => {
-                    if(this.selSchools.includes(item.id)) {
-                        this.createData.invitedSchools.push({
-                            id: item.id,
-                            name: item.name,
-                            picture: item.picture
-                        })
+        async nextNew() {
+            switch(this.current) {
+                case 2: //保存活动
+                    // 1. 由前端创建本次活动的id
+                    if(!this.isEdit) this.createData.id = this.$tools.guid()
+                    // 2. 将封面、附件上传至blob,并填充 createData 中的 poster attachment
+                    // 2.1 先合并 封面 + 要上传的附件
+                    let files = this.posterFile.file ? [this.posterFile.file].concat(this.attachAdd) : this.attachAdd
+                    console.log(files);
+                    // 2.2 编辑状态下需先删除原已上传的附件
+                    if(this.attachDel.length) {
+                        let delType = await this.deleteBlob(this.attachDel)
+                        if(!delType) {
+                            this.$Message.warning('保存失败!')
+                            return
+                        }
                     }
-                })
-                this.fields.forEach(item => {
-                    let infos = this.infoArr.find(info => {
-                        return info.field === item
+                    // 2.3 上传 封面 + 附件
+                    let fileBlob = await this.uploadBlob(files)
+                    console.log(fileBlob);
+                    // 2023.11.10 处理编辑状态下没有保存已有且未被删除的文件,只保存了当前新增的
+                    this.createData.attachment = this.attachment.map(item => {
+                        console.log(item);
+                        if(item.hash) {
+                            return item
+                        } else {
+                            let newFile = fileBlob.find(files => {
+                                return files.name === item.name
+                            })
+                            console.log(newFile);
+                            newFile.hash = this.$tools.convertFileMD5ToString(newFile.md5)
+                            newFile.cnt = this.isArea ? this.areaId : this.$store.state.userInfo.schoolCode
+                            return newFile
+                        }
                     })
-                    if(infos) this.contestData.sign.fields.push(infos)
-                })
-                this.current += 1
+                    /* this.createData.attachment = fileBlob.map(item => {
+                        item.hash = this.$tools.convertFileMD5ToString(item.md5)
+                        item.cnt = this.isArea ? this.areaId : this.$store.state.userInfo.schoolCode
+                        return item
+                    }) */
+                    // 编辑状态下,未修改封面,posterFile.file为空,不需要重新赋值poster
+                    if(this.posterFile.file) {
+                        this.createData.poster = fileBlob[0].url
+                        this.createData.attachment.shift()
+                    } else {
+                        // 编辑状态下的poster 拼接了sas,保存时需去掉
+                        this.createData.poster = this.posterFile.url.slice(0, this.posterFile.url.lastIndexOf('?'))
+                    }
+                    // 3. 若有新创建的评审规则,需先保存,保存大活动时由后端一起保存
+                    this.saveActivity()
+                    break
+                case 1:
+                    // 加入发布活动页面前需保存学校列表、填报信息
+                    console.log(111111111);
+                    this.createData.invitedSchools = []
+                    this.contestData.sign.fields = []
+                    this.showSchools.forEach(item => {
+                        if(this.selSchools.includes(item.id)) {
+                            this.createData.invitedSchools.push({
+                                id: item.id,
+                                name: item.name,
+                                picture: item.picture
+                            })
+                        }
+                    })
+                    this.infoArr.forEach(item => {
+                        if(this.fields.includes(item.field)) {
+                            this.contestData.sign.fields.push(item)
+                        }
+                    })
+                default:
+                    this.current += 1
+                    console.log(33333333333)
+                    break
             }
         },
         uploadBlob(fileList) {
             return new Promise((r, j) => {
                 // 先将封面、附件保存在blob: (区级id/学校编码)/activity/活动id/attachment/文件
                 // 获取初始化Blob需要的数据
-                let sasData = {
+                /* let sasData = {
                     url: this.$store.state.user.userProfile.blob_uri.split('/' + this.$store.state.userInfo.TEAMModelId)[0],
                     sas: '',
-                }
+                } */
                 let code = this.isArea ? this.areaId : this.$store.state.userInfo.schoolCode
                 let scope = this.isArea ? 'area' : 'school'
                 let path = `activity/${this.createData.id}/attachment`
-                if(this.isArea) {
+                /* if(this.isArea) {
                     sasData.sas = this.$store.state.user.userProfile.areas.find(item => {
                         return item.areaId === this.areaId
                     }).sas
                 } else {
                     sasData.sas = this.$store.state.user.schoolProfile.blob_sas
                 }
-                console.log(sasData);
+                console.log(sasData); */
                 //初始化Blob
-                let blobTool = new BlobTool(sasData.url, code, "?" + sasData.sas, scope)
+                let blobTool = new BlobTool(this.sasData.url, code, "?" + this.sasData.sas, scope)
                 let promiseArr = []
                 console.log(fileList);
                 fileList.map(item => {
@@ -1032,17 +1190,35 @@ export default {
                 })
             })
         },
+        deleteBlob(files) {
+            return new Promise((r, j) => {
+                //初始化Blob
+                let code = this.isArea ? this.areaId : this.$store.state.userInfo.schoolCode
+                let scope = this.isArea ? 'area' : 'school'
+                let blobTool = new BlobTool(this.sasData.url, code, "?" + this.sasData.sas, scope)
+                let fileUrl = files.map(item => {
+                    return item.blob
+                })
+                console.log(fileUrl);
+                blobTool.deleteBlobBatch(fileUrl).then(() => {
+                    r(true)
+                }).catch(() => {
+                    j(false)
+                })
+                r(true)
+            })
+        },
         last() {
             this.current -= 1
         },
         // 获取大活动的进行时间
         getCreateTime(data) {
-            this.createTime = data.filter(item => {
+            this.actAllTime[0] = data.filter(item => {
                 return item
             })
-            if (this.createTime.length > 1) {
-                this.createData.stime = (new Date(this.createTime[0])).getTime()
-                this.createData.etime = (new Date(this.createTime[1])).getTime()
+            if (this.actAllTime[0].length > 1) {
+                this.createData.stime = (new Date(this.actAllTime[0][0])).getTime()
+                this.createData.etime = (new Date(this.actAllTime[0][1])).getTime()
             }
         },
         // 优课评选的报名时间
@@ -1087,9 +1263,6 @@ export default {
         },
         // 文件展示
         customUpload(file) {
-            // 点击发布活动时,上传到blob,再回传blob地址
-            // sas等根据get-school-info areas 中有返回url、sas
-            console.log(file);
             // 有限制格式
             /* if(this.homeworkInfo.extLimit.length) {
                 let extension = file.name.substring(file.name.lastIndexOf(".") + 1, file.name.length).toLowerCase()
@@ -1102,9 +1275,11 @@ export default {
                 this.$Message.warning(this.$t("studentWeb.homework.sizeOver"))
                 return false
             } */
+            // 点击发布活动时,上传到blob,再回传blob地址
+            console.log(file);
             let newFile = {
-                file,
-                name: file.name,
+                file: new File([file], "CoverImage.jpg", {type: file.type}),
+                name: 'CoverImage.jpg', //封面固定名称
                 size: file.size,
                 type: file.type,
                 progress: 0,
@@ -1118,7 +1293,6 @@ export default {
                     file: newFile
                 }
             }
-            // this.posterFile = newFile
             return false
         },
         //重新上传
@@ -1130,6 +1304,12 @@ export default {
             }
         },
         customUploadFile(file) {
+            if(this.attachment.find(item => {
+                return item.name === file.name
+            })) {
+                this.$Message.warning('存在相同文件,请重新上传!')
+                return
+            }
             let newFile = {
                 file,
                 name: file.name,
@@ -1148,13 +1328,25 @@ export default {
                 hash: '',
                 cnt: '', //容器名: 公开(醍摩豆智慧学区id) 区级(区级编码) 校级(学校编码)
             } */
+            this.attachAdd.push(newFile)
             this.attachment.push(newFile)
         },
         // 删除选择的文件
-        delUpload(index) {
+        delUpload(index, data) {
+            // 编辑状态下,删除已经保存在blob的文件需加入数组
+            if(this.isEdit && data.blob) {
+                this.attachDel.push(data)
+            } else {
+                // 新增的需从 attachAdd 删除
+                let delIndex = this.attachAdd.findIndex(item => {
+                    return item.name === data.name
+                })
+                if(delIndex != -1) this.attachAdd.splice(delIndex, 1)
+            }
             this.attachment.splice(index, 1)
         },
         initStatus(data) {
+            console.log(data);
             this.tabListShow = this.tabList.filter(item => {
                 return data.includes(item.name)
             })

+ 29 - 8
TEAMModelOS/ClientApp/src/view/signupActivity/infoReleased.vue

@@ -15,7 +15,7 @@
                 <div class="btn-box" v-if="actInfo.needConfirmed || !actInfo.publish">
                     <template v-if="!actInfo.needConfirmed">
                         <Button type="success" size="small" @click="publishNow()">立即发布</Button>
-                        <Button type="primary" size="small">修改</Button>
+                        <Button type="primary" size="small" @click="editInfo()">修改</Button>
                         <Button type="warning" size="small" @click="delAct()">删除</Button>
                     </template>
                     <template v-else>
@@ -58,9 +58,10 @@
                         </div>
                         <div v-if="actInfo.scope != 'school' && isArea">
                             <span>学校:</span>
-                            <span>
+                            <span v-if="actInfo.invitedSchools.length">
                                 <span v-for="item in actInfo.invitedSchools" :key="item.id">{{ item.name }}</span>
                             </span>
+                            <span v-else>未限制学校</span>
                         </div>
                         <div>
                             <span>免责声明:</span>
@@ -68,9 +69,10 @@
                         </div>
                         <div style="display: flex;">
                             <p style="min-width: 50px;">附件:</p>
-                            <div>
+                            <div v-if="actInfo.attachment.length">
                                 <p v-for="item in actInfo.attachment" :key="item.blob">{{ item.name }}</p>
                             </div>
+                            <span v-else>暂无</span>
                         </div>
                     </template>
                 </div>
@@ -84,11 +86,12 @@
                                     </span>
                                 </p>
                                 <p>填报信息:
-                                    <span class="info-border" v-for="(item, index) in contestInfo.sign.fieldName" :key="index">{{ item }}</span>
+                                    <span class="info-border" v-for="(item, index) in contestInfo.sign.fields" :key="index">{{ item.field }}</span>
                                 </p>
                                 <p>报名人数:
                                     <!-- <span class="info-border">{{ '28' }}人</span> -->
-                                    {{ contestInfo.sign.limit }}人
+                                    <span v-if="contestInfo.sign.limit">{{ contestInfo.sign.limit }}人</span>
+                                    <span v-else>-</span>
                                 </p>
                                 <p>参赛方式:
                                     <!-- <span class="info-border">{{ '团队赛' }}</span> -->
@@ -281,7 +284,7 @@ export default {
                 if(res.code === 200) {
                     this.$Message.success('发布成功')
                     this.$router.push({
-                        name: this.actInfo.scope === 'area' ? 'areaInfoActivity' : 'infoActivity',
+                        name: this.actInfo.scope != 'school' ? 'areaInfoActivity' : 'infoActivity',
                         params: {
                             info: res.activity
                         }
@@ -291,6 +294,16 @@ export default {
                 }
             })
         },
+        editInfo() {
+            this.$router.push({
+                name: this.isArea ? 'areaCreateActivity' : "createActivity",
+                params: {
+                    info: this.actInfo,
+                    contest: this.contestInfo,
+                    reviewRule: this.ruleInfo
+                },
+            })
+        },
         delAct() {
             this.$Modal.confirm({
                 title: '确定删除本次活动吗?',
@@ -305,6 +318,15 @@ export default {
                     this.$api.areaActivity.manageAct(params).then(res => {
                         if(res.code === 201) {
                             this.$Message.success('删除成功')
+                            // 显示只能删除本人管理的文件夹,需处理
+                            this.$api.blob.deletePrefix({
+                                "cntr": this.actInfo.owner,
+                                "prefix": `activity/${this.actInfo.id}`
+                            }).then(res => {
+                                if(res.status) {
+                                    console.log('删除成功!');
+                                }
+                            })
                             this.$router.go(-1)
                         } else if(res.code === 200) {
                             this.$Message.warning('删除失败')
@@ -331,8 +353,7 @@ export default {
                 }
             })
         },
-    }
-
+    },
 }
 </script>
 

+ 3 - 1
TEAMModelOS/ClientApp/src/view/signupActivity/processActivity.vue

@@ -105,7 +105,9 @@ export default {
                         item.endTime = this.$tools.formatTime(item.etime, 'yyyy-MM-dd')
                         item.poster = !item.poster ? require('@/assets/image/no-poster-cn1.png') : `${item.poster}?${item.sas}`
                         item.attachment.forEach(attach => {
-                            attach.url = `${attach.url}?${item.sas}`
+                            if(attach) {
+                                attach.url = `${attach.url}?${item.sas}`
+                            }
                         })
                         // 校级确认参加: confirmedSchools[0].status = 0(没确认)/1(已确认)
                         // 区级都需要确认,公开只有选择了学校才需确认

+ 246 - 72
TEAMModelOS/ClientApp/src/view/signupActivity/setActivity.vue

@@ -29,7 +29,7 @@
                             </div>
                             <span v-else>
                                 {{ row.name }}
-                                <Icon type="md-contact" v-if="areaId === row.id" />
+                                <Icon type="md-contact" size="17" color="#ff6f00" v-if="areaId === row.id" />
                             </span>
                         </template>
                         <template #allowPublic="{row}">
@@ -61,27 +61,32 @@
                         <FormItem>
                             <Button @click="editType = true" v-show="!editType">更改</Button>
                             <div v-show="editType">
-                                <Button type="primary" @click="saveWebsit(websitInfo, false)">保存</Button>
+                                <Button type="primary" @click="saveWebsit(websitInfo, false, false)">保存</Button>
                                 <Button @click="cancelInfo()" class="cancel-edit">取消</Button>
                             </div>
                         </FormItem>
                     </Form>
                 </template>
             </TabPane>
-            <TabPane label="首页管理" name="homepage">
-                <Button @click="bannerShow = true">新增</Button>
-                <Table :columns="columns" :data="bannnerdata" class="banner-set">
-                    <template #type="{row}">
-                        <span>{{ row.type ? '区级' : '公开' }}</span>
+            <TabPane label="首页管理" name="homepage" style="margin: 0 20px;">
+                <Button type="primary" @click="addBannerType()">新增</Button>
+                <!-- <Carousel v-model="bannerValue" loop>
+                    <CarouselItem v-for="(item, index) in bannerdata.banners" :key="index">
+                        <img :src="item.blobSas" alt="">
+                    </CarouselItem>
+                </Carousel> -->
+                <Table :columns="columns" :data="bannerdata.banners" class="banner-set banner-list">
+                    <template #blobSas="{row}">
+                        <img :src="row.blobSas" alt="">
                     </template>
-                    <template #state="{row}">
-                        <Alert :type="row.state === 1 ? 'success' : 'warning'" v-if="row.state">
-                            {{ row.state === 1 ? '进行中' : '已结束' }}
-                        </Alert>
-                        <Alert v-else>未开始</Alert>
+                    <template #url="{row}">
+                        <span>{{ row.url || '-' }}</span>
                     </template>
-                    <template #image="{row}">
-                        <img :src="row.image" alt="">
+                    <template #time="{row}">
+                        <span>{{ $tools.formatTime(row.time, 'yyyy-MM-dd') }}</span>
+                    </template>
+                    <template #expire="{row}">
+                        <span>{{ $tools.formatTime(row.expire, 'yyyy-MM-dd') }}</span>
                     </template>
                     <template #action="{}">
                         <Button type="error" size="small">删除</Button>
@@ -89,16 +94,54 @@
                 </Table>
             </TabPane>
         </Tabs>
-        <Modal v-model="bannerShow" title="新增首页展示" @on-ok="addBanner()">
-            <Select v-model="awardsSel" style="width:200px">
-                <Option v-for="(item, index) in awardsList" :value="index" :key="index">{{ item.name }}</Option>
-            </Select>
+        <Modal v-model="bannerShow" title="添加首页展示" :footer-hide="true">
+            <Tabs v-model="bannerTab">
+                <TabPane label="新建首页展示" name="form">
+                    <Form :model="awardsData" :label-width="80">
+                        <FormItem label="标题">
+                            <Input v-model="awardsData.title" placeholder="Enter something..."></Input>
+                        </FormItem>
+                        <FormItem label="副标题">
+                            <Input v-model="awardsData.subtitle" placeholder="Enter something..."></Input>
+                        </FormItem>
+                        <FormItem label="跳转地址">
+                            <Input v-model="awardsData.url" placeholder="Enter something..."></Input>
+                        </FormItem>
+                        <FormItem label="开始时间">
+                            <DatePicker @on-change="(data) => awardsData.time = (new Date(data)).getTime()" transfer type="date" placeholder="Select date" />
+                        </FormItem>
+                        <FormItem label="结束时间">
+                            <DatePicker @on-change="(data) => awardsData.expire = (new Date(data)).getTime()" transfer type="date" placeholder="Select date" />
+                        </FormItem>
+                        <FormItem label="展示图片">
+                            <Upload v-show="!showFile.url" multiple type="drag" action="" :before-upload="customUpload" :show-upload-list="false" accept=".jpg, .jpeg, .png, .gif">
+                                <div style="padding: 20px 0">
+                                    <Icon type="ios-cloud-upload" size="52" style="color: #3399ff"></Icon>
+                                    <p>上传主题图片</p>
+                                </div>
+                            </Upload>
+                            <img v-if="showFile.url" :src="showFile.url" alt="" width="500">
+                            <p v-show="showFile.url" class="repeat-upload" @click="repeatUpload">{{$t('td.td58')}}</p>
+                        </FormItem>
+                    </Form>
+                </TabPane>
+                <TabPane label="活动列表选择" name="list">
+                    <CheckboxGroup v-model="actBanner">
+                        <Checkbox :label="item.id" v-for="(item, index) in activityList" :key="index">
+                            <span>{{ item.name }}</span>
+                        </Checkbox>
+                    </CheckboxGroup>
+                </TabPane>
+            </Tabs>
+            <Button type="success" long @click="saveWebsit(null, false, true)">保存</Button>
         </Modal>
     </div>
 </template>
 
 
 <script>
+import BlobTool from "@/utils/blobTool.js"
+
 export default {
     data () {
         return {
@@ -141,38 +184,36 @@ export default {
 
             columns: [
                 {
-                    title: '活动名称',
-                    key: 'name',
+                    title: '图片',
+                    slot: 'blobSas',
+                    width: '200',
                     align: 'center',
                 },
                 {
-                    title: '申办人',
-                    key: 'people',
+                    title: '标题',
+                    key: 'title',
                     align: 'center',
-                    width: '100',
                 },
                 {
-                    title: '醍摩豆ID',
-                    key: 'tmdid',
+                    title: '副标题',
+                    key: 'subtitle',
                     align: 'center',
-                    width: '200',
                 },
                 {
-                    title: '活动类型',
-                    slot: 'type',
+                    title: '跳转地址',
+                    slot: 'url',
                     align: 'center',
-                    width: '100',
                 },
                 {
-                    title: '活动状态',
-                    slot: 'state',
+                    title: '开始时间',
+                    slot: 'time',
                     width: '150',
                     align: 'center',
                 },
                 {
-                    title: '图片',
-                    slot: 'image',
-                    width: '200',
+                    title: '结束时间',
+                    slot: 'expire',
+                    width: '150',
                     align: 'center',
                 },
                 {
@@ -182,16 +223,7 @@ export default {
                     align: 'center',
                 }
             ],
-            bannnerdata: [
-                {
-                    name: '2019第八届科技领导卓越奖',
-                    people: '罗老师',
-                    tmdid: '1595321354',
-                    type: 0,
-                    state: 0,
-                    image: require('./demo.jpeg'),
-                },
-            ],
+            bannerdata: {},
             editType: false,
             bannerShow: false,
             awardsList: [
@@ -204,7 +236,23 @@ export default {
                     image: require('./demo.jpeg'),
                 },
             ],
-            awardsSel: [],
+            awardsData: {
+                title: '', //标题
+                subtitle: '', //副标题
+                url: '', //跳转的路由地址
+                blob: '', //文件的blob地址
+                fileType: '',
+                time: 0, //开始展示的时间
+                expire: 0, //展示到期时间
+            },
+            showFile: {
+                url: '',
+                file: undefined
+            },
+            activityList: [],
+            actBanner: [],
+            bannerTab: 'form',
+            bannerValue: 0,
         }
     },
     computed: {
@@ -214,6 +262,14 @@ export default {
         areaId() {
             return sessionStorage.getItem('areaId')
         },
+        sasData() {
+            return {
+                url: this.$store.state.user.userProfile.blob_uri.split('/' + this.$store.state.userInfo.TEAMModelId)[0],
+                sas: this.$store.state.user.userProfile.areas.find(item => {
+                    return item.areaId === this.areaId
+                }).sas,
+            }
+        },
     },
     created () {
         this.getWebsite()
@@ -235,29 +291,141 @@ export default {
                             return item
                         })
                         this.websiteInitial = this._.cloneDeep(this.websiteList)
+                        this.bannerdata = res.websites.find(item => {
+                            return item.id === this.areaId
+                        })
+                        this.bannerdata.banners.map(item => {
+                            item.blobSas = item.blob + '?' + this.sasData.sas
+                        })
                     }
                 }
             })
         },
-        saveWebsit(row, isTable) {
+        
+        uploadBlob(file) {
+            return new Promise((r, j) => {
+                // 手动添加的文件地址: 区级id/activity/banner/文件
+                // 获取初始化Blob需要的数据
+                let path = `activity/banner`
+                //初始化Blob
+                let blobTool = new BlobTool(this.sasData.url, this.areaId, "?" + this.sasData.sas, 'area')
+                blobTool.upload(file.file, {path, checkSize: false}, {
+                    onProgress: (e) => {
+                        file.progress = parseInt(e.loadedBytes * 100 / file.size)
+                    }
+                }).then(res => {
+                    r(res)
+                }).catch(e => {
+                    j(e)
+                })
+            })
+        },
+        async saveWebsit(row, isTable, isBanner) {
+            let websiteData = this._.cloneDeep(this.bannerdata)
+            if(isBanner) {
+                switch(this.bannerTab) {
+                    case 'form':
+                        let blob = await this.uploadBlob(this.showFile)
+                        this.awardsData.blob = blob.url
+                        this.awardsData.fileType = this.showFile.file.type
+                        websiteData.banners.push(this.awardsData)
+                        break
+                    case 'list':
+                        this.activityList.forEach(item => {
+                            if(this.actBanner.includes(item.id)) {
+                                websiteData.banners.push({
+                                    title: item.name, //标题
+                                    subtitle: item.subject, //副标题
+                                    url: '', //跳转的路由地址
+                                    blob: item.poster, //文件的blob地址
+                                    fileType: 'image/jpg',
+                                    time: item.stime, //开始展示的时间
+                                    expire: item.etime, //展示到期时间
+                                })
+                            }
+                        })
+                        break
+                }
+            }
             let params = {
                 grant_type: 'update',
                 areaId: this.areaId,
-                website: row,
+                website: isBanner ? websiteData : row,
             }
             this.$api.areaActivity.websiteManage(params).then(res => {
                 if(res.code === 200) {
                     this.$Message.success('更新成功')
-                    if(isTable) {
-                        row.isEdit = false
+                    if(!isBanner) {
+                        if(isTable) {
+                            row.isEdit = false
+                        } else {
+                            this.editType = false
+                        }
                     } else {
-                        this.editType = false
+                        this.bannerdata = websiteData
+                        this.bannerShow = false
                     }
                 } else {
                     this.$Message.warning('更新失败')
                 }
             })
         },
+        addBannerType() {
+            this.getActivityList()
+            this.bannerShow = true
+        },
+        getActivityList() {
+            let params = {
+                grant_type: 'list-area',
+                year: localStorage.getItem('curSemester').year,
+                areaId: this.areaId,
+            }
+            this.$api.areaActivity.manageAct(params).then(res => {
+                if(res.activities) {
+                    this.activityList = res.activities.map(item => {
+                        item.startTime = this.$tools.formatTime(item.stime, 'yyyy-MM-dd')
+                        item.endTime = this.$tools.formatTime(item.etime, 'yyyy-MM-dd')
+                        /* item.poster = !item.poster ? require('@/assets/image/no-poster-cn1.png') : `${item.poster}?${item.sas}`
+                        item.attachment.forEach(attach => {
+                            if(attach) {
+                                attach.url = `${attach.url}?${item.sas}`
+                            }
+                        }) */
+                        return item
+                    })
+                }
+            })
+        },
+        // 文件展示
+        customUpload(file) {
+            // 点击发布活动时,上传到blob,再回传blob地址
+            console.log(file);
+            let newFile = {
+                // file: new File([file], "CoverImage.jpg", {type: file.type}),
+                name: file.name, //封面固定名称
+                size: file.size,
+                type: file.type,
+                progress: 0,
+            }
+            const reader = new FileReader()
+            reader.readAsDataURL(file)
+            reader.onload = () => {
+                const _base64 = reader.result
+                this.showFile = {
+                    url: _base64,
+                    file: newFile
+                }
+            }
+            return false
+        },
+        //重新上传
+        repeatUpload() {
+            // this.$refs['upd-poster'].clearFiles()
+            this.showFile = {
+                url: '',
+                file: undefined
+            }
+        },
         cancelEdit(row, index) {
             row.name = this.websiteInitial[index].name
             row.allowPublic = this.websiteInitial[index].allowPublic
@@ -268,35 +436,41 @@ export default {
             this.websitInfo.allowPublic = this.websitInitial.allowPublic
             this.editType = false
         },
-        addBanner() {
-            this.bannnerdata.push(this.awardsList[this.awardsSel])
-        },
     }
 }
 </script>
 
 <style lang="less" scoped>
-.banner-set {
-    img{
-        width: 100%;
-    }
-    .ivu-alert {
-        text-align: center;
-        padding: 5px 0;
-    }
-    .website-name-edit {
-        display: flex;
-        align-items: center;
-        .ivu-icon {
-            margin-left: 10px;
+.setting {
+    .banner-set {
+        img{
+            width: 100%;
         }
-    }
-    .cancel-edit {
-        background-color: #959595;
-        border-color: #959595;
-        color: #fff;
-        &:hover {
+        .ivu-alert {
+            text-align: center;
+            padding: 5px 0;
+        }
+        .website-name-edit {
+            display: flex;
+            align-items: center;
+            .ivu-icon {
+                margin-left: 10px;
+            }
+        }
+        .cancel-edit {
+            background-color: #959595;
             border-color: #959595;
+            color: #fff;
+            &:hover {
+                border-color: #959595;
+            }
+        }
+    }
+    .banner-list {
+        margin-top: 20px;
+
+        img {
+            max-width: 150px;
         }
     }
 }

+ 2 - 2
TEAMModelOS/Controllers/Student/StudentController.cs

@@ -979,8 +979,8 @@ namespace TEAMModelOS.Controllers
                 }
                 //2.將OpenID放入學生Base
                 student.openId = openId;
-                await studentClient.ReplaceItemAsync(student, student.id);
-                //3.學生登入流程
+                //await studentClient.ReplaceItemAsync(student, student.id);
+                //3.學生登入流程(包含學生資料更新)
                 (string ip, string region) = await LoginService.LoginIp(HttpContext, _searcher);
                 (string auth_token, string blob_uri, string blob_sas, object classinfo, List<object> courses, AuthenticationResult token) = await StudentCheck(school, $"{student.id}", $"{student.classId}", $"{schoolCode}", $"{student.picture}", $"{student.name}", schoolClient, teacherClient, school.areaId, ip, client, student);
                 int countAuthorized = await GetStudentAuthNumByScale($"{schoolCode}", school);