licailing 4 vuotta sitten
vanhempi
commit
9491d20ff8

+ 1 - 0
src/main/java/com/izouma/wenlvju/domain/performance/Performance.java

@@ -73,6 +73,7 @@ public class Performance extends BaseEntity {
     private BigDecimal reviewRatio;
 
     private boolean close;
+    private boolean rate;
 
     @Transient
     private long programmeNum;

+ 3 - 11
src/main/java/com/izouma/wenlvju/domain/performance/Programme.java

@@ -95,21 +95,10 @@ public class Programme extends BaseEntity {
 
     private int process;
 
-//    @ApiModelProperty(value = "流程")
-//    @Enumerated(EnumType.STRING)
-//    private ProgrammeProcess programmeProcess;
-
     @ApiModelProperty(value = "签到管理")
     @Enumerated(EnumType.STRING)
     private SignedIn signedIn;
 
-//    @Column(columnDefinition = "TEXT")
-//    @ApiModelProperty(value = "情况说明")
-//    private String description;
-//
-//    @ApiModelProperty(value = "签到时间")
-//    private LocalDateTime signedAt;
-
     @ApiModelProperty(value = "参演人数")
     private int quantity;
 
@@ -137,6 +126,9 @@ public class Programme extends BaseEntity {
     @ApiModelProperty(value = "奖项")
     private Long awardId;
 
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
     @Transient
     private String specialty;
 

+ 31 - 0
src/main/java/com/izouma/wenlvju/dto/ScoreDTO.java

@@ -0,0 +1,31 @@
+package com.izouma.wenlvju.dto;
+
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel(value = "节目评审")
+public class ScoreDTO {
+    private Long programmeId;
+
+    private Double score;
+
+    private LocalDateTime markAt;
+
+    @Column(columnDefinition = "TEXT")
+    private String remark;
+
+    private Long expertId;
+
+    private Long performanceId;
+
+}

+ 0 - 24
src/main/java/com/izouma/wenlvju/enums/ProgrammeProcess.java

@@ -1,24 +0,0 @@
-package com.izouma.wenlvju.enums;
-/**
- * 审核流程
- */
-public enum ProgrammeProcess {
-
-    /*
-    待分组
-     */
-    ARRANGE,
-    /*
-    待分配评委
-     */
-    ARRANGE_JUDGE,
-    /*
-    待签到
-     */
-    SIGN_IN,
-    /*
-    待评分
-     */
-    RATE
-
-}

+ 16 - 5
src/main/java/com/izouma/wenlvju/service/MessageService.java

@@ -17,8 +17,10 @@ import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
 import javax.transaction.Transactional;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
@@ -35,17 +37,26 @@ public class MessageService {
         return messageRepo.findAll(JpaUtils.toSpecification(pageQuery, Message.class), JpaUtils.toPageRequest(pageQuery));
     }
 
-    public byte[] excelTemp(HttpServletResponse response) throws IOException {
+    public void excelTemp(HttpServletResponse response) throws IOException {
         // 设置response的Header
         response.setContentType("application/vnd.ms-excel");
         response.setHeader("Content-Disposition", "attachment; filename=" + "Phone.xlsx");
 
         InputStream is = getClass().getResourceAsStream("/templates/Phone.xlsx");
-        byte[] buffer = new byte[is.available()];
+        byte[] buffer = new byte[1024];
+        int len;
 
-        is.read(buffer);
-        is.close();
-        return buffer;
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        while ((len = is.read(buffer)) > -1) {
+            outputStream.write(buffer, 0, len);
+        }
+        outputStream.flush();
+
+        ServletOutputStream sos = response.getOutputStream();
+        sos.write(outputStream.toByteArray());
+
+        sos.flush();
+        outputStream.close();
     }
 
     @Transactional(rollbackOn = Exception.class)

+ 0 - 2
src/main/java/com/izouma/wenlvju/service/performance/ArrangeJudgeService.java

@@ -8,7 +8,6 @@ import com.izouma.wenlvju.domain.performance.Arrange;
 import com.izouma.wenlvju.domain.performance.ArrangeJudge;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.exception.BusinessException;
-import com.izouma.wenlvju.repo.RateAuditRepo;
 import com.izouma.wenlvju.repo.UserRepo;
 import com.izouma.wenlvju.repo.performance.ArrangeJudgeRepo;
 import com.izouma.wenlvju.repo.performance.ArrangeRepo;
@@ -32,7 +31,6 @@ public class ArrangeJudgeService {
     private ArrangeRepo      arrangeRepo;
     private UserRepo         userRepo;
     private NjwlSmsService   njwlSmsService;
-    private RateAuditRepo    rateAuditRepo;
 
     public Page<ArrangeJudge> all(PageQuery pageQuery) {
         return arrangeJudgeRepo.findAll(JpaUtils.toSpecification(pageQuery, ArrangeJudge.class), JpaUtils.toPageRequest(pageQuery));

+ 105 - 3
src/main/java/com/izouma/wenlvju/service/performance/ArrangeService.java

@@ -1,9 +1,13 @@
 package com.izouma.wenlvju.service.performance;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.exception.ExcelAnalysisException;
+import com.alibaba.excel.exception.ExcelDataConvertException;
 import com.alibaba.fastjson.JSONObject;
 import com.izouma.wenlvju.domain.ArtType;
-import com.izouma.wenlvju.domain.RateAudit;
 import com.izouma.wenlvju.domain.User;
 import com.izouma.wenlvju.domain.performance.Arrange;
 import com.izouma.wenlvju.domain.performance.ArrangeJudge;
@@ -11,23 +15,29 @@ import com.izouma.wenlvju.domain.performance.Performance;
 import com.izouma.wenlvju.domain.performance.Programme;
 import com.izouma.wenlvju.dto.ArrangeDTO;
 import com.izouma.wenlvju.dto.PageQuery;
+import com.izouma.wenlvju.dto.ProgrammeDTO;
 import com.izouma.wenlvju.enums.PerformanceStatus;
 import com.izouma.wenlvju.enums.ProgrammeStatus;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.repo.ArtTypeRepo;
-import com.izouma.wenlvju.repo.RateAuditRepo;
 import com.izouma.wenlvju.repo.UserRepo;
 import com.izouma.wenlvju.repo.performance.ArrangeJudgeRepo;
 import com.izouma.wenlvju.repo.performance.ArrangeRepo;
 import com.izouma.wenlvju.repo.performance.PerformanceRepo;
 import com.izouma.wenlvju.repo.performance.ProgrammeRepo;
 import com.izouma.wenlvju.utils.JpaUtils;
+import com.izouma.wenlvju.utils.excel.UploadDataListener;
 import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.persistence.criteria.Predicate;
+import javax.transaction.Transactional;
+import java.io.IOException;
+import java.io.InputStream;
 import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
@@ -37,6 +47,7 @@ import java.util.Set;
 import java.util.stream.Collectors;
 
 @Service
+@Slf4j
 @AllArgsConstructor
 public class ArrangeService {
 
@@ -47,7 +58,6 @@ public class ArrangeService {
     private ArrangeJudgeRepo arrangeJudgeRepo;
     private UserRepo         userRepo;
     private PerformanceRepo  performanceRepo;
-    private RateAuditRepo    rateAuditRepo;
 
     public Page<Arrange> all(PageQuery pageQuery) {
         Map<Long, String> artMap = artTypeRepo.findAll()
@@ -403,4 +413,96 @@ public class ArrangeService {
         });
     }
 
+    @Transactional(rollbackOn = Exception.class)
+    public List<ProgrammeDTO> upload(MultipartFile file) {
+
+        try {
+            InputStream fis = file.getInputStream();
+            UploadDataListener<ProgrammeDTO> listener = new UploadDataListener<>();
+            return EasyExcel.read(fis, ProgrammeDTO.class, listener)
+                    .sheet()
+                    .doReadSync();
+
+
+        } catch (ExcelAnalysisException e) {
+            e.printStackTrace();
+            if (e.getCause() instanceof ExcelDataConvertException) {
+                ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) e.getCause();
+                String cellMsg = "";
+                String errorMsg = String.format("excel表格:第%s行,第%s列,数据值为:%s,该数据值不符合要求,请检验后重新导入!请检查其他的记录是否有同类型的错误!", excelDataConvertException.getRowIndex() + 1, excelDataConvertException.getColumnIndex(), cellMsg);
+                log.error(errorMsg);
+                throw new BusinessException(errorMsg);
+            }
+
+        } catch (IOException e) {
+            log.error("上传失败", e);
+            throw new BusinessException("上传失败", e.getMessage());
+        }
+        return null;
+    }
+
+    public void saveProgramme(MultipartFile file) {
+
+        List<ProgrammeDTO> programmeDTOS = this.upload(file);
+        if (CollUtil.isEmpty(programmeDTOS)) {
+            return;
+        }
+
+        Performance performance = performanceRepo.findByYear(String.valueOf(LocalDate.now().getYear()));
+        if (LocalDate.now().isBefore(performance.getEndDate())) {
+            throw new BusinessException("活动报名未结束");
+        }
+        PerformanceStatus status = performance.getStatus();
+        // 第一次分组
+        if (PerformanceStatus.UNDER_REVIEW.equals(status)) {
+            // 直接分配评委
+            performance.setStatus(PerformanceStatus.ARRANGE_JUDGE);
+            if (performance.getAuditTimes() == 0) {
+                performance.setAuditTimes(1);
+            }
+
+            performanceRepo.save(performance);
+        }
+        // 节目id
+        List<Long> ids = programmeDTOS.stream().map(ProgrammeDTO::getId).distinct().collect(Collectors.toList());
+        List<Programme> programmes = programmeRepo.findAllById(ids);
+        // 专业
+        List<Long> specialtyId = programmes.stream()
+                .map(Programme::getParentSpecialtyId)
+                .distinct()
+                .collect(Collectors.toList());
+        specialtyId.remove(null);
+        long count = arrangeRepo.countArrangeByPerformanceId(performance.getId()) + 1;
+        // 新建分组
+        Arrange arrange = arrangeRepo.save(Arrange.builder()
+                .name("第" + count + "组")
+                .auditTimes(1)
+                .specialtyId(specialtyId)
+                .quantity(programmes.size())
+                .performanceId(performance.getId())
+                .auditTimes(performance.getAuditTimes())
+                .build());
+
+        // 保存分组
+        programmeRepo.setArrangeId(arrange.getId(), ids);
+
+        // 分配评委
+        // 查找名字
+        String originalFilename = file.getOriginalFilename();
+        if (StrUtil.isEmpty(originalFilename)) {
+            throw new BusinessException("文件名为空!");
+        }
+        int end = originalFilename.lastIndexOf(".");
+        String orginalName = originalFilename.substring(0, end);
+        User user = userRepo.findByPhoneAndDelFalse(orginalName);
+        if (ObjectUtil.isNull(user)) {
+            throw new BusinessException("无评委");
+        }
+        // 保存评委
+        arrangeJudgeRepo.save(ArrangeJudge.builder()
+                .arrangeId(arrange.getId())
+                .expertId(user.getId())
+                .auditTimes(arrange.getAuditTimes())
+                .build());
+    }
 }

+ 48 - 0
src/main/java/com/izouma/wenlvju/service/performance/ProgrammeScoreService.java

@@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil;
 import com.izouma.wenlvju.domain.performance.Performance;
 import com.izouma.wenlvju.domain.performance.ProgrammeScore;
 import com.izouma.wenlvju.dto.PageQuery;
+import com.izouma.wenlvju.dto.ScoreDTO;
 import com.izouma.wenlvju.enums.PerformanceStatus;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.repo.performance.PerformanceRepo;
@@ -126,5 +127,52 @@ public class ProgrammeScoreService {
         }
         programmeScoreRepo.save(programmeScore);
     }
+
+    public void saveScore(ScoreDTO dto) {
+        Performance performance = performanceRepo.findById(dto.getPerformanceId())
+                .orElseThrow(new BusinessException("无活动"));
+        if (!performance.isRate()) {
+            throw new BusinessException("不可评分");
+        }
+        // 改状态
+        if (!PerformanceStatus.RATE.equals(performance.getStatus())) {
+            performance.setStatus(PerformanceStatus.RATE);
+            performanceRepo.save(performance);
+        }
+
+
+        ProgrammeScore programmeScore = programmeScoreRepo.findByProgrammeIdAndExpertId(dto.getProgrammeId(), dto.getExpertId());
+        LocalDateTime now = LocalDateTime.now();
+        if (ObjectUtil.isNull(programmeScore)) {
+            programmeScore = ProgrammeScore.builder()
+                    .expertId(dto.getExpertId())
+                    .programmeId(dto.getProgrammeId())
+                    .score(dto.getScore())
+                    .markAt(now)
+                    .auditTimes(performance.getAuditTimes())
+                    .remark(dto.getRemark())
+                    .build();
+        } else {
+            if (StrUtil.isNotEmpty(dto.getRemark())) {
+                programmeScore.setRemark(dto.getRemark());
+            }
+            if (ObjectUtil.isNotNull(dto.getScore())) {
+                programmeScore.setScore(dto.getScore());
+                programmeScore.setMarkAt(now);
+            }
+        }
+
+        programmeScoreRepo.save(programmeScore);
+        Object avgObj = programmeScoreRepo.avgScore(dto.getProgrammeId());
+        if (ObjectUtil.isNotNull(avgObj)) {
+            Double avg = Convert.convert(Double.class, avgObj);
+            if (programmeScore.getAuditTimes() > 1) {
+                programmeRepo.reviewScore(avg, dto.getProgrammeId());
+                return;
+            }
+            programmeRepo.score(avg, dto.getProgrammeId());
+        }
+
+    }
 }
 

+ 8 - 5
src/main/java/com/izouma/wenlvju/service/performance/ProgrammeService.java

@@ -865,11 +865,14 @@ public class ProgrammeService {
                 dto.setRemark(programmeScore.getRemark());
                 dto.setSecond(programmeScore.isSecond());
             }
-            List<String> participants = participantMap.get(programme.getId())
-                    .stream()
-                    .map(Participant::getName)
-                    .collect(Collectors.toList());
-            dto.setParticipant(participants);
+            if (CollUtil.isNotEmpty(participantMap)){
+                List<String> participants = participantMap.get(programme.getId())
+                        .stream()
+                        .map(Participant::getName)
+                        .collect(Collectors.toList());
+                dto.setParticipant(participants);
+            }
+
             return dto;
         });
     }

+ 2 - 2
src/main/java/com/izouma/wenlvju/web/MessageController.java

@@ -73,8 +73,8 @@ public class MessageController extends BaseController {
     }
 
     @GetMapping(value = "/excelTemp", produces = "application/vnd.ms-excel;charset=utf-8")
-    public byte[] excelTemp(HttpServletResponse response) throws IOException {
-        return messageService.excelTemp(response);
+    public void excelTemp(HttpServletResponse response) throws IOException {
+        messageService.excelTemp(response);
     }
 
     @PostMapping("/upload")

+ 6 - 0
src/main/java/com/izouma/wenlvju/web/performance/ArrangeController.java

@@ -16,6 +16,7 @@ import lombok.AllArgsConstructor;
 import org.springframework.data.domain.Page;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -85,5 +86,10 @@ public class ArrangeController extends BaseController {
     public Page<Arrange> byExpert(@RequestBody PageQuery pageQuery) {
         return arrangeService.byExpert(pageQuery, SecurityUtils.getAuthenticatedUser().getId());
     }
+
+    @PostMapping("/upload")
+    public void upload(@RequestParam("file") MultipartFile file) {
+        arrangeService.saveProgramme(file);
+    }
 }
 

+ 7 - 0
src/main/java/com/izouma/wenlvju/web/performance/ProgrammeScoreController.java

@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
 import com.izouma.wenlvju.domain.User;
 import com.izouma.wenlvju.domain.performance.ProgrammeScore;
 import com.izouma.wenlvju.dto.PageQuery;
+import com.izouma.wenlvju.dto.ScoreDTO;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.repo.performance.ProgrammeScoreRepo;
 import com.izouma.wenlvju.service.performance.ProgrammeScoreService;
@@ -69,6 +70,12 @@ public class ProgrammeScoreController extends BaseController {
                 .getId());
     }
 
+    @ApiOperation("专家手机端打分")
+    @PostMapping("/mark")
+    public void mark(@RequestBody ScoreDTO record) {
+        programmeScoreService.saveScore(record);
+    }
+
     @ApiOperation("打分细则")
     @PostMapping("/breakdown")
     public List<ProgrammeScore> breakdown(@RequestParam Long programmeId) {

+ 8 - 0
src/main/vue/src/router.js

@@ -655,6 +655,14 @@ const router = new Router({
                         title: '分配评委'
                     }
                 },
+                {
+                    path: '/judgeList',
+                    name: 'JudgeList',
+                    component: () => import(/* webpackChunkName: "JudgeList" */ '@/views/performance/JudgeList.vue'),
+                    meta: {
+                        title: '分配评委'
+                    }
+                },
                 {
                     path: '/programmeSignList',
                     name: 'ProgrammeSignList',

+ 623 - 0
src/main/vue/src/views/performance/JudgeList.vue

@@ -0,0 +1,623 @@
+<template>
+    <div class="list-view">
+        <div class="filters-container">
+            <el-form :model="form" :rules="rules" size="mini" ref="form" inline label-width="100px">
+                <el-form-item label="活动名称" prop="performanceId">
+                    <el-select
+                        v-model="form.performanceId"
+                        filterable
+                        placeholder="活动名称"
+                        style="width: 300px"
+                        @change="getData"
+                    >
+                        <el-option
+                            v-for="item in performances"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value"
+                        >
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item>
+                    <el-button type="primary" @click="intoGroup">查看未分组情况情况</el-button>
+                    <el-upload
+                        :action="uploadUrl"
+                        :before-upload="beforeUpload"
+                        :headers="headers"
+                        :show-file-list="false"
+                        ref="upload"
+                        :on-success="onSuccess"
+                        class="uploader"
+                        :on-error="onfail"
+                        :loading="loading"
+                        :disabled="loading"
+                    >
+                        <el-button
+                            slot="trigger"
+                            type="primary"
+                            icon="el-icon-upload2"
+                            :loading="loading"
+                            :disabled="loading"
+                            >导入分组</el-button
+                        >
+                    </el-upload>
+                </el-form-item>
+            </el-form>
+        </div>
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            empty-text="暂无数据"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+            :height="tableHeight"
+        >
+            <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
+            <el-table-column prop="address" label="活动地点" v-if="!online"> </el-table-column>
+            <el-table-column prop="name" label="分组名称" min-width="130"> </el-table-column>
+            <el-table-column label="时间安排" min-width="100" v-if="!online">
+                <template slot-scope="{ row }"> {{ getTime(row.startTime) }}-{{ getTime(row.endTime) }} </template>
+            </el-table-column>
+            <el-table-column prop="quantity" label="节目数量"> </el-table-column>
+            <el-table-column label="参赛专业">
+                <template slot-scope="{ row }">
+                    {{ row.specialtyName ? row.specialtyName.join(',') : '' }}
+                </template>
+            </el-table-column>
+            <el-table-column label="评审专家" min-width="130" prop="experts"> </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" :min-width="online ? 160 : 320">
+                <template slot-scope="{ row }">
+                    <el-button
+                        @click="editRow(row)"
+                        type="primary"
+                        size="mini"
+                        plain
+                        v-if="performance.status == 'ARRANGE' && !online"
+                        >编辑</el-button
+                    >
+                    <el-button @click="assignAExpert(row)" type="primary" size="mini" plain>分配评委</el-button>
+                    <el-button @click="programme(row)" size="mini" plain>查看节目</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <el-pagination
+                background
+                @size-change="onSizeChange"
+                @current-change="onCurrentChange"
+                :current-page="page"
+                :page-sizes="[10, 20, 30, 40, 50]"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalElements"
+            >
+            </el-pagination>
+        </div>
+
+        <el-dialog :visible.sync="showProgramme" width="80%" title="未分组节目" center>
+            <el-table
+                :data="unGrouped"
+                row-key="id"
+                empty-text="暂无数据"
+                header-row-class-name="table-header-row"
+                header-cell-class-name="table-header-cell"
+                row-class-name="table-row"
+                cell-class-name="table-cell"
+                height="500"
+            >
+                <el-table-column prop="name" label="节目名称"> </el-table-column>
+                <el-table-column prop="specialty" label="参赛专业"> </el-table-column>
+                <el-table-column
+                    prop="competitionGroup"
+                    label="参赛组别"
+                    :formatter="competitionGroupFormatter"
+                    min-width="70"
+                >
+                </el-table-column>
+                <el-table-column prop="level" label="参赛级别" min-width="70"> </el-table-column>
+                <el-table-column prop="durationOfWork" label="作品时长" min-width="70"> </el-table-column>
+                <el-table-column prop="quantity" label="参赛人数" min-width="70"> </el-table-column>
+                <el-table-column prop="gradingOrganization" label="考级机构" min-width="160"> </el-table-column>
+                <el-table-column prop="organization" label="承办单位" min-width="160"> </el-table-column>
+                <el-table-column prop="examPoint" label="考级点"> </el-table-column>
+            </el-table>
+        </el-dialog>
+        <arrange-log :dialogVisible="isShow" @close="isShow = false" ref="public"></arrange-log>
+        <organ-log
+            :tableData="tableData"
+            :dialogVisible="isJudge"
+            @close="isJudge = false"
+            ref="publicOrgan"
+        ></organ-log>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+import ArrangeLog from '../../components/ArrangeLog';
+import OrganLog from '../../components/OrganLog';
+import { time } from 'echarts';
+import delChild from '@/mixins/delChild';
+import resolveUrl from 'resolve-url';
+
+export default {
+    name: 'JudgeList',
+    mixins: [pageableTable, delChild],
+    components: { ArrangeLog, OrganLog },
+    data() {
+        return {
+            showMore: false,
+            multipleMode: false,
+            search: '',
+            isShow: false,
+            url: '/arrange/all2',
+            downloading: false,
+            form: {},
+            performances: [],
+            performance: {},
+            addresses: [],
+            addressList: [],
+            timeRange: [null, null],
+            dateRange: '',
+            afterTimeRange: [null, null],
+            artTypes: [],
+            showProgramme: false,
+            unGrouped: [],
+            competitionGroupOptions: [
+                { label: '个人', value: 'SINGLE' },
+                { label: '集体', value: 'COLLECTIVE' }
+            ],
+            times: [3, 5, 10, 15, 20],
+            activeNames: [],
+            online: false,
+            loading: false,
+            uploadUrl: '',
+            isJudge: false
+        };
+    },
+    watch: {
+        timeRange(value) {
+            let checked = value.includes(null);
+            // console.log(value[0] + ':00');
+            this.form.morning = !checked;
+            this.$refs.form.validateField('afternoon');
+        },
+        afterTimeRange(value) {
+            let checked = value.includes(null);
+            console.log(checked);
+            this.form.afternoon = !checked;
+        }
+    },
+    created() {
+        this.uploadUrl = resolveUrl(this.$baseUrl, 'arrange/upload');
+        this.$http
+            .post(
+                '/performance/all',
+                {
+                    size: 100,
+                    sort: 'year,desc',
+                    query: {
+                        publish: true
+                    }
+                },
+                { body: 'json' }
+            )
+            .then(res => {
+                if (res.content.length > 0) {
+                    res.content.forEach(item => {
+                        this.performances.push({
+                            label: item.name,
+                            value: item.id
+                        });
+                    });
+                    this.form.performanceId = res.content[0].id;
+                    this.performance = res.content[0];
+                    this.online = this.performance.online;
+                    if (this.review) {
+                        this.online = this.performance.reviewOnline;
+                    }
+                    this.getData();
+                    this.$http
+                        .post(
+                            '/performanceSchedule/all',
+                            { size: 100, query: { performanceId: this.form.performanceId } },
+                            { body: 'json' }
+                        )
+                        .then(res => {
+                            if (res.content.length > 0) {
+                                res.content.forEach(item => {
+                                    this.addressList.push({
+                                        value: item.address,
+                                        pid: item.performanceId
+                                    });
+                                });
+                            }
+                        })
+                        .catch(e => {
+                            console.log(e);
+                            this.$message.error(e.error);
+                        });
+                }
+            })
+            .catch(e => {
+                console.log(e);
+                this.$message.error(e.error);
+            });
+
+        this.$http
+            .post('/artType/parent')
+            .then(res => {
+                if (res.length > 0) {
+                    res.forEach(item => {
+                        this.artTypes.push({
+                            label: item.name,
+                            value: item.id
+                        });
+                    });
+                }
+            })
+            .catch(e => {
+                console.log(e);
+                this.$message.error(e.error);
+            });
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        },
+        rules() {
+            return {
+                performanceId: [{ required: true, message: '请选择活动名称', trigger: 'blur' }],
+                address: [{ required: true, message: '请输入活动地点', trigger: 'blur' }],
+                quantity: [{ required: true, message: '请输入分组节目数量', trigger: 'blur' }],
+                duration: [{ required: true, message: '请输入单个节目时长', trigger: 'blur' }],
+                morning: [
+                    {
+                        validator: (rule, value, callback) => {
+                            callback();
+                        },
+                        trigger: 'change'
+                    }
+                ],
+                afternoon: [
+                    {
+                        validator: (rule, value, callback) => {
+                            if (this.form.afternoon || this.form.morning) {
+                                callback();
+                            } else {
+                                callback(new Error('请选择时间安排!'));
+                            }
+                        },
+                        trigger: 'change'
+                    }
+                ]
+            };
+        },
+        headers() {
+            return {
+                Authorization: 'Bearer ' + sessionStorage.getItem('token')
+            };
+        }
+    },
+    methods: {
+        competitionGroupFormatter(row, column, cellValue, index) {
+            let selectedOption = this.competitionGroupOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        beforeGetData() {
+            let data = {
+                search: this.search,
+                query: {
+                    performanceId: this.form.performanceId
+                }
+            };
+            if (this.review) {
+                data.query.auditTimes = this.performance.auditTimes;
+            } else {
+                data.query.auditTimes = 1;
+            }
+            return data;
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/arrangeEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        editRow(row) {
+            this.isShow = true;
+            this.$refs.public.init(row.id);
+        },
+        programme(row) {
+            if (this.online) {
+                if (this.review) {
+                    this.$router.push({
+                        path: '/progGroupOnlineList',
+                        query: {
+                            arid: row.id
+                        }
+                    });
+                } else {
+                    this.$router.push({
+                        path: '/progGroupOnlineList',
+                        query: {
+                            aid: row.id
+                        }
+                    });
+                }
+            } else {
+                if (this.review) {
+                    this.$router.push({
+                        path: '/programmeGroupList',
+                        query: {
+                            arid: row.id
+                        }
+                    });
+                } else {
+                    this.$router.push({
+                        path: '/programmeGroupList',
+                        query: {
+                            aid: row.id
+                        }
+                    });
+                }
+            }
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/arrange/excel', {
+                    responseType: 'blob',
+                    params: { size: 10000 }
+                })
+                .then(res => {
+                    console.log(res);
+                    this.downloading = false;
+                    const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
+                    const link = document.createElement('a');
+                    link.href = downloadUrl;
+                    link.setAttribute('download', res.headers['content-disposition'].split('filename=')[1]);
+                    document.body.appendChild(link);
+                    link.click();
+                    link.remove();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.downloading = false;
+                    this.$message.error(e.error);
+                });
+        },
+        operation1() {
+            this.$notify({
+                title: '提示',
+                message: this.selection
+            });
+        },
+        operation2() {
+            this.$message('操作2');
+        },
+        deleteRow(row) {
+            this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/arrange/del/${row.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        },
+        group() {
+            this.$refs.form.validate(valid => {
+                if (valid) {
+                    this.submit();
+                } else {
+                    return false;
+                }
+            });
+        },
+        submit() {
+            let data = { ...this.form };
+            data.startDate = this.dateRange[0];
+            data.endDate = this.dateRange[1];
+            if (this.timeRange[0] != null || this.timeRange[1] != null) {
+                data.morningStartTime = this.timeRange[0] + ':00';
+                data.morningEndTime = this.timeRange[1] + ':00';
+            }
+            if (this.afterTimeRange[0] != null || this.afterTimeRange[1] != null) {
+                data.afternoonStartTime = this.afterTimeRange[0] + ':00';
+                data.afternoonEndTime = this.afterTimeRange[1] + ':00';
+            }
+            this.saving = true;
+            this.$http
+                .post('/arrange/group', data, { body: 'json' })
+                .then(res => {
+                    this.saving = false;
+                    this.$message.success('成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.saving = false;
+                    this.$message.error(e.error);
+                });
+        },
+        submitOffline() {
+            let data = { ...this.form };
+            this.saving = true;
+            this.$http
+                .post('/arrange/group', data, { body: 'json' })
+                .then(res => {
+                    this.saving = false;
+                    this.$message.success('成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.saving = false;
+                    this.$message.error(e.error);
+                });
+        },
+        move(index, direction) {
+            const start = index;
+            const end = direction + index;
+            const startInfo = { ...this.tableData[start] };
+            const endInfo = { ...this.tableData[end] };
+            Promise.all([
+                this.$http.post(
+                    '/arrange/save',
+                    {
+                        ...startInfo,
+                        startTime: endInfo.startTime,
+                        endTime: endInfo.endTime,
+                        name: endInfo.name
+                    },
+                    { body: 'json' }
+                ),
+                this.$http.post(
+                    '/arrange/save',
+                    {
+                        ...endInfo,
+                        startTime: startInfo.startTime,
+                        endTime: startInfo.endTime,
+                        name: startInfo.name
+                    },
+                    { body: 'json' }
+                )
+            ])
+                .then(_ => {
+                    this.loading = false;
+                    this.getData();
+                    this.$message.success('成功');
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.loading = false;
+                    this.$message.error(e.error);
+                });
+        },
+        intoGroup() {
+            this.showProgramme = true;
+            this.$http
+                .post('/programme/unGrouped', { performanceId: this.form.performanceId })
+                .then(res => {
+                    if (res.length > 0) this.unGrouped = res;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.$message.error(e.error);
+                });
+        },
+        clear() {
+            this.form = {
+                address: '',
+                morning: '',
+                afternoon: '',
+                quantity: '',
+                duration: '',
+                specialtyId: ''
+            };
+            this.dateRange = '';
+            this.timeRange = [null, null];
+            this.afterTimeRange = [null, null];
+            this.$nextTick(() => {
+                this.$refs.form.resetFields();
+            });
+        },
+        handleChange(val) {},
+        publishGroup() {
+            this.$alert('发布后分组信息及节目分组情况不能修改,确认要发布么?', '警告', { type: 'error' })
+                .then(() => {
+                    return this.$http.post(`/arrange/publish`, { performanceId: this.form.performanceId });
+                })
+                .then(() => {
+                    this.$message.success('发布成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        },
+        canEdit() {
+            let can = this.performance.status == 'UNDER_REVIEW' || this.performance.status == 'ARRANGE';
+            return can;
+        },
+        upload() {},
+        onfail(e) {
+            console.log(e);
+            this.$message.error('失败:' + e);
+            this.loading = false;
+            this.getData();
+        },
+        onSuccess() {
+            this.$message.success('上传成功');
+            this.loading = false;
+            this.getData();
+        },
+        beforeUpload() {
+            return this.$confirm('确认要上传文件吗?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'warning'
+            }).then(() => {
+                this.loading = true;
+            });
+        },
+        assignAExpert(row) {
+            this.isJudge = true;
+            this.$refs.publicOrgan.init(row.id);
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.flex {
+    display: flex;
+    width: 100%;
+    /deep/ .el-form-item__content {
+        flex-grow: 1;
+
+        .el-select {
+            width: 100%;
+        }
+    }
+}
+/deep/ .el-form-item__label {
+    width: 150px !important;
+}
+/deep/ .el-card__body {
+    padding: 20px 0 !important;
+}
+.time {
+    width: 120px;
+    margin-left: 15px;
+    & + .time {
+        margin-left: 10px;
+    }
+}
+.uploader {
+    display: inline-block;
+    margin: 0 10px;
+}
+</style>

+ 5 - 4
src/main/vue/src/views/performance/ProgGroupOnlineList.vue

@@ -17,8 +17,9 @@
                         {{ row.specialtyName.join(',') }}
                     </template>
                 </el-table-column>
-                <el-table-column prop="writerDirector" label="编导姓名"> </el-table-column>
-                <el-table-column prop="phone" label="联系电话"> </el-table-column>
+                <!-- <el-table-column prop="writerDirector" label="编导姓名"> </el-table-column>
+                <el-table-column prop="phone" label="联系电话"> </el-table-column> -->
+                <el-table-column label="评审专家" min-width="130" prop="experts"> </el-table-column>
             </el-table>
             <el-button style="margin: 10px" @click="intoGroup" type="primary">添加节目</el-button>
         </div>
@@ -274,7 +275,7 @@ export default {
         showCode(row) {
             this.dialogCode = true;
             this.dialogUrl =
-                'http://wljtest.izouma.com/h5/home?performanceId=' +
+                'http://yskj.njlyw.cn:8081/h5/home?performanceId=' +
                 row.performanceId +
                 '&performanceApplyId=' +
                 row.id;
@@ -337,7 +338,7 @@ export default {
         },
         getArrange(aid) {
             this.$http
-                .post('/arrange/all', { query: { id: aid } }, { body: 'json' })
+                .post('/arrange/all2', { query: { id: aid } }, { body: 'json' })
                 .then(res => {
                     this.arrange = res.content;
                     this.performanceId = res.content[0].performanceId;

+ 538 - 0
src/main/vue/src/views/performance/ProgrammeScoreList copy.vue

@@ -0,0 +1,538 @@
+<template>
+    <div class="list-view">
+        <div class="filters-container">
+            <el-form :model="form" size="mini" inline>
+                <el-row>
+                    <el-col :span="24">
+                        <el-form-item label="活动名称">
+                            <el-select
+                                v-model="performanceId"
+                                clearable
+                                filterable
+                                placeholder="活动名称"
+                                style="width: 300px"
+                                @change="changeAddress"
+                            >
+                                <el-option
+                                    v-for="item in performances"
+                                    :key="item.value"
+                                    :label="item.label"
+                                    :value="item.value"
+                                >
+                                </el-option>
+                            </el-select>
+                        </el-form-item>
+                        <el-form-item>
+                            <el-button @click="getData" type="primary" icon="el-icon-search">查询 </el-button>
+                        </el-form-item>
+                    </el-col>
+                    <div v-if="!online">
+                        <el-form-item label="活动日期">
+                            <el-date-picker v-model="date" type="date" placeholder="选择日期" class="filter-item">
+                            </el-date-picker>
+                        </el-form-item>
+                        <el-form-item label="时间">
+                            <el-radio-group v-model="morning" @change="getData" class="filter-item">
+                                <el-radio-button :label="true">上午</el-radio-button>
+                                <el-radio-button :label="false">下午</el-radio-button>
+                            </el-radio-group>
+                        </el-form-item>
+                        <el-form-item label="活动地点">
+                            <el-select v-model="form.address" class="filter-item">
+                                <el-option
+                                    v-for="(item, index) in addresses"
+                                    :key="index"
+                                    :value="item.value"
+                                    :label="item.value"
+                                ></el-option>
+                            </el-select>
+                        </el-form-item>
+                    </div>
+                    <!-- <el-form-item label="评审专家"></el-form-item> -->
+                </el-row>
+            </el-form>
+        </div>
+        <el-table
+            :data="tableData"
+            row-key="id"
+            ref="table"
+            header-row-class-name="table-header-row"
+            header-cell-class-name="table-header-cell"
+            row-class-name="table-row"
+            cell-class-name="table-cell"
+            :height="tableHeight"
+            :span-method="objectSpanMethod"
+        >
+            <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
+            <!-- <el-table-column prop="id" label="ID" width="100"> </el-table-column> -->
+            <el-table-column prop="arrangeName" label="分组" min-width="160"> </el-table-column>
+            <el-table-column prop="name" label="节目名称" min-width="70"> </el-table-column>
+            <el-table-column prop="specialty" label="参赛专业"> </el-table-column>
+            <el-table-column prop="participant" label="参赛人员" show-overflow-tooltip>
+                <template slot-scope="{ row }">{{
+                    row.participant ? row.participant.join(',') : row.participant
+                }}</template>
+            </el-table-column>
+            <el-table-column prop="quantity" label="表演人数" min-width="70"> </el-table-column>
+            <el-table-column prop="signedIn" label="状态" :formatter="signedInFormatter" v-if="!online">
+            </el-table-column>
+            <el-table-column prop="score" label="成绩"> </el-table-column>
+            <el-table-column prop="myScore" label="评分" align="center" min-width="120">
+                <template slot-scope="{ row }">
+                    <span v-if="row.second">{{ row.myScore }}</span>
+                    <el-input-number
+                        v-else
+                        v-model="row.myScore"
+                        size="mini"
+                        label=""
+                        :min="0"
+                        :max="100"
+                        :step="1"
+                        :controls="true"
+                        controls-position="both"
+                        @change="saveScore(row)"
+                    >
+                    </el-input-number>
+                </template>
+            </el-table-column>
+            <el-table-column prop="remark" label="备注" align="center" min-width="120">
+                <template slot-scope="{ row }">
+                    <span v-if="row.second">{{ row.remark }}</span>
+                    <el-input
+                        v-else
+                        size="mini"
+                        @change="saveScore(row)"
+                        v-model="row.remark"
+                        placeholder="请输入备注"
+                        clearable
+                    ></el-input>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" align="left" fixed="right" min-width="100">
+                <template slot-scope="{ row, $index }">
+                    <el-button @click="playVideo(row, $index)" size="mini" plain type="primary">查看作品</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+        <div class="pagination-wrapper">
+            <!-- <div class="multiple-mode-wrapper">
+                <el-button v-if="!multipleMode" @click="toggleMultipleMode(true)">批量编辑</el-button>
+                <el-button-group v-else>
+                    <el-button @click="operation1">批量操作1</el-button>
+                    <el-button @click="operation2">批量操作2</el-button>
+                    <el-button @click="toggleMultipleMode(false)">取消</el-button>
+                </el-button-group>
+            </div> -->
+            <el-pagination
+                background
+                @size-change="onSizeChange"
+                @current-change="onCurrentChange"
+                :current-page="page"
+                :page-sizes="[10, 20, 30, 40, 50]"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="totalElements"
+            >
+            </el-pagination>
+        </div>
+
+        <el-dialog class="videoDialog" destroy-on-close center append-to-body :visible.sync="showViedo" width="60%">
+            <video
+                :src="programme.video"
+                controls
+                style="height: 600px; width: 85%; margin: 0 auto"
+                v-if="programme.video"
+            >
+                您的浏览器不支持 video 标签。
+            </video>
+            <div style="height: 85%; width: 85%;margin: 0 auto">
+                <img style="height: 100%; width: 100%; " :src="programme.annex" alt="" v-if="programme.annex" />
+            </div>
+            <el-card shadow="never" style="width: 85%; margin: 10px auto">
+                <el-form :form="programme">
+                    <el-form-item label="分数">
+                        <span v-if="programme.second">{{ programme.myScore }}</span>
+                        <el-input-number
+                            v-else
+                            v-model="programme.myScore"
+                            size="mini"
+                            label=""
+                            :min="0"
+                            :max="100"
+                            :step="1"
+                            :controls="true"
+                            controls-position="both"
+                        >
+                        </el-input-number>
+                    </el-form-item>
+                    <el-form-item label="备注">
+                        <span v-if="programme.second">{{ programme.remark }}</span>
+                        <el-input
+                            v-else
+                            size="mini"
+                            v-model="programme.remark"
+                            placeholder="请输入备注"
+                            style="width: 200px"
+                            clearable
+                        ></el-input>
+                    </el-form-item>
+
+                    <el-form-item>
+                        <el-button size="mini" v-if="!programme.second" @click="saveScore(programme)" type="primary"
+                            >保存</el-button
+                        >
+                        <el-button size="mini" @click="move(-1)" :disabled="index == 0">上一个</el-button>
+                        <el-button
+                            size="mini"
+                            @click="move(1)"
+                            :disabled="(page - 1) * pageSize + index == totalElements - 1 || index >= pageSize - 1"
+                            >下一个</el-button
+                        >
+                        <el-button @click="showViedo = false" size="mini">关闭</el-button>
+                    </el-form-item>
+                </el-form>
+            </el-card>
+            <!-- <video
+                :src="videoUrl"
+                controlsList="nodownload noremote footbar"
+                controls
+                style="height: 100%; max-width: 100%"
+                ref="video"
+                v-if="showViedo"
+            >
+                您的浏览器不支持 video 标签。
+            </video> -->
+        </el-dialog>
+    </div>
+</template>
+<script>
+import delChild from '@/mixins/delChild';
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+import QrcodeVue from 'qrcode.vue';
+import { format, isSameDay, startOfDay } from 'date-fns';
+import endOfDay from 'date-fns/endOfDay';
+import addHours from 'date-fns/addHours';
+
+export default {
+    name: 'ProgrammeScoreList',
+    mixins: [pageableTable, delChild],
+    props: ['review'],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/programme/byScore',
+            downloading: false,
+            form: {},
+            dialogSign: false,
+            performanceId: '',
+            performances: [],
+            performance: {},
+            signedInOptions: [
+                { label: '已签到', value: 'SIGNED_IN' },
+                { label: '未签到', value: 'UNSIGNED' },
+                { label: '已调整', value: 'ADJUSTED' }
+            ],
+            signForm: {},
+            addresses: [],
+            morning: true,
+            date: new Date(),
+            columnKeys: ['arrangeName'],
+            addressList: [],
+            showViedo: false,
+            programme: {},
+            index: 0,
+            online: true
+        };
+    },
+    created() {
+        this.morning = isSameDay(addHours(new Date(), 12), new Date());
+
+        this.$http
+            .post(
+                '/performance/all',
+                {
+                    size: 1000,
+                    sort: 'year,desc',
+                    query: {
+                        publish: true
+                    }
+                },
+                { body: 'json' }
+            )
+            .then(res => {
+                if (res.content.length > 0) {
+                    res.content.forEach(item => {
+                        this.performances.push({
+                            label: item.name,
+                            value: item.id
+                        });
+                    });
+                    this.setPerformance(res.content[0]);
+                    this.getData();
+                    this.$http
+                        .post('/performanceSchedule/all', { size: 100 }, { body: 'json' })
+                        .then(res => {
+                            if (res.content.length > 0) {
+                                res.content.forEach(item => {
+                                    this.addressList.push({
+                                        value: item.address,
+                                        pid: item.performanceId
+                                    });
+                                });
+                            }
+                        })
+                        .catch(e => {
+                            console.log(e);
+                            this.$message.error(e.error);
+                        });
+                }
+            })
+            .catch(e => {
+                console.log(e);
+                this.$message.error(e.error);
+            });
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        },
+        showTable() {
+            return this.backMap(this.tableData);
+        }
+    },
+    methods: {
+        signedInFormatter(row, column, cellValue, index) {
+            let selectedOption = this.signedInOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        beforeGetData() {
+            let data = {
+                query: {
+                    auditTimes: 1
+                }
+            };
+            if (this.performanceId) {
+                data.query.performanceId = this.performanceId;
+            }
+            if (this.review) {
+                data.query.auditTimes = this.performance.auditTimes || 1;
+            }
+            // if (this.date) {
+            //     if (this.morning) {
+            //         data.query.showBegin = [
+            //             format(startOfDay(this.date), 'yyyy-MM-dd HH:mm:ss'),
+            //             format(this.date, 'yyyy-MM-dd') + ' 12:00:00'
+            //         ].join(',');
+            //     } else {
+            //         data.query.showBegin = [
+            //             format(this.date, 'yyyy-MM-dd') + ' 12:00:00',
+            //             format(endOfDay(this.date), 'yyyy-MM-dd HH:mm:ss')
+            //         ].join(',');
+            //     }
+            // }
+
+            return data;
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        showSign(row) {
+            this.dialogSign = true;
+            this.signForm.id = row.id;
+        },
+        operation1() {
+            this.$notify({
+                title: '提示',
+                message: this.selection
+            });
+        },
+        operation2() {
+            this.$message('操作2');
+        },
+        signIn() {
+            this.$alert('确认签到?', '提示', { type: 'primary' })
+                .then(() => {
+                    return this.$http.post('/programme/signIn', {
+                        id: this.signForm.id,
+                        signedIn: this.signForm.signedIn,
+                        description: this.signForm.description
+                    });
+                })
+                .then(() => {
+                    this.$message.success('签到成功');
+                    this.dialogSign = false;
+                    this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        },
+        saveScore(row) {
+            if (!row.myScore) {
+                this.$message.warning('请输入评分');
+                return;
+            }
+            this.$http
+                .post('/programmeScore/saveScore?programmeId=' + row.id, {
+                    score: row.myScore,
+                    remark: row.remark,
+                    performanceId: row.performanceId
+                })
+                .then(res => {
+                    this.$message.success('评分成功');
+                    this.getData();
+                    this.programme = res;
+                })
+                .catch(e => {
+                    this.$message.error(e.error);
+                });
+        },
+        backMap(list, key = 'arrangeName', preActive = 0) {
+            let _map = new Map();
+            list.forEach((item, index) => {
+                let info = {
+                    active: index + preActive,
+                    childNum: 1,
+                    list: []
+                };
+                if (_map.has(item[key])) {
+                    info = _map.get(item[key]);
+                    info.list.push(item);
+                    info.childNum = info.list.length;
+                } else {
+                    info.list.push(item);
+                }
+
+                _map.set(item[key], info);
+            });
+
+            let keyIndex = this.columnKeys.indexOf(key);
+            if (keyIndex !== this.columnKeys.length - 1) {
+                [..._map.keys()].forEach(item => {
+                    let info = _map.get(item);
+                    let childMap = this.backMap(info.list, this.columnKeys[keyIndex + 1], info.active);
+                    _map.set(item, {
+                        ...info,
+                        childMap: childMap
+                    });
+                });
+            }
+
+            return _map;
+        },
+        getInfo(mapInfo = new Map(), keys = ['date']) {
+            let info = {};
+            keys.forEach(item => {
+                if (mapInfo.has(item)) {
+                    info = mapInfo.get(item);
+                    mapInfo = mapInfo.get(item).childMap;
+                }
+            });
+            return info;
+        },
+        objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+            let keyIndex = columnIndex;
+            // if (column.label === '操作') {
+            //     keyIndex = 2;
+            // }
+
+            if (keyIndex < this.columnKeys.length) {
+                let keys = [...this.columnKeys].slice(0, keyIndex + 1).map(item => {
+                    return row[item];
+                });
+                let info = this.getInfo(this.showTable, keys);
+                if (rowIndex === info.active) {
+                    return {
+                        rowspan: info.childNum,
+                        colspan: 1
+                    };
+                } else {
+                    return {
+                        rowspan: 0,
+                        colspan: 0
+                    };
+                }
+            }
+        },
+        playVideo(row, index) {
+            this.index = index;
+            this.showViedo = true;
+            this.programme = row;
+        },
+        move(direction) {
+            const end = direction + this.index;
+            this.programme = { ...this.tableData[end] };
+            this.index = end;
+        },
+        setPerformance(row) {
+            this.form.performanceId = row.id;
+            this.performance = row;
+            this.online = row.online;
+            if (this.review) {
+                this.online = this.reviewOnline;
+            }
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.right {
+    float: right;
+}
+/deep/.el-form-item--mini.el-form-item,
+.el-form-item--small.el-form-item {
+    margin-bottom: 10px;
+}
+.videoDialog {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    .el-dialog {
+        max-width: 900px;
+        margin-top: 0px;
+
+        .close {
+            position: absolute;
+            right: 0px;
+            top: -42px;
+            width: 71px;
+            height: 32px;
+            background: #00000015;
+
+            font-size: 12px;
+            color: #fdffff;
+            line-height: 32px;
+            text-align: center;
+            cursor: pointer;
+
+            &:hover {
+                background: #00000055;
+            }
+        }
+    }
+    .el-dialog__header {
+        display: none;
+    }
+
+    .el-dialog__body {
+        padding: 0;
+
+        video {
+            display: block;
+            height: auto;
+            width: 100%;
+            outline: none;
+        }
+    }
+}
+</style>

+ 19 - 19
src/main/vue/src/views/performance/ProgrammeScoreList.vue

@@ -69,7 +69,9 @@
             <el-table-column prop="name" label="节目名称" min-width="70"> </el-table-column>
             <el-table-column prop="specialty" label="参赛专业"> </el-table-column>
             <el-table-column prop="participant" label="参赛人员" show-overflow-tooltip>
-                <template slot-scope="{ row }">{{ row.participant.join(',') }}</template>
+                <template slot-scope="{ row }">{{
+                    row.participant ? row.participant.join(',') : row.participant
+                }}</template>
             </el-table-column>
             <el-table-column prop="quantity" label="表演人数" min-width="70"> </el-table-column>
             <el-table-column prop="signedIn" label="状态" :formatter="signedInFormatter" v-if="!online">
@@ -77,8 +79,8 @@
             <el-table-column prop="score" label="成绩"> </el-table-column>
             <el-table-column prop="myScore" label="评分" align="center" min-width="120">
                 <template slot-scope="{ row }">
-                    <span v-if="row.second">{{ row.myScore }}</span>
-                    <el-input-number
+                    <span>{{ row.myScore }}</span>
+                    <!-- <el-input-number
                         v-else
                         v-model="row.myScore"
                         size="mini"
@@ -90,20 +92,20 @@
                         controls-position="both"
                         @change="saveScore(row)"
                     >
-                    </el-input-number>
+                    </el-input-number> -->
                 </template>
             </el-table-column>
             <el-table-column prop="remark" label="备注" align="center" min-width="120">
                 <template slot-scope="{ row }">
-                    <span v-if="row.second">{{ row.remark }}</span>
-                    <el-input
+                    <span>{{ row.remark }}</span>
+                    <!-- <el-input
                         v-else
                         size="mini"
                         @change="saveScore(row)"
                         v-model="row.remark"
                         placeholder="请输入备注"
                         clearable
-                    ></el-input>
+                    ></el-input> -->
                 </template>
             </el-table-column>
             <el-table-column label="操作" align="left" fixed="right" min-width="100">
@@ -149,9 +151,8 @@
             <el-card shadow="never" style="width: 85%; margin: 10px auto">
                 <el-form :form="programme">
                     <el-form-item label="分数">
-                        <span v-if="programme.second">{{ programme.myScore }}</span>
+                        <!-- <span v-if="programme.second">{{ programme.myScore }}</span> -->
                         <el-input-number
-                            v-else
                             v-model="programme.myScore"
                             size="mini"
                             label=""
@@ -164,9 +165,8 @@
                         </el-input-number>
                     </el-form-item>
                     <el-form-item label="备注">
-                        <span v-if="programme.second">{{ programme.remark }}</span>
+                        <!-- <span v-if="programme.second">{{ programme.remark }}</span> -->
                         <el-input
-                            v-else
                             size="mini"
                             v-model="programme.remark"
                             placeholder="请输入备注"
@@ -176,9 +176,7 @@
                     </el-form-item>
 
                     <el-form-item>
-                        <el-button size="mini" v-if="!programme.second" @click="saveScore(programme)" type="primary"
-                            >保存</el-button
-                        >
+                        <el-button size="mini" @click="saveScore(programme)" type="primary">保存</el-button>
                         <el-button size="mini" @click="move(-1)" :disabled="index == 0">上一个</el-button>
                         <el-button
                             size="mini"
@@ -380,12 +378,14 @@ export default {
                 this.$message.warning('请输入评分');
                 return;
             }
+            let record = {
+                programmeId: row.id,
+                score: row.myScore,
+                remark: row.remark,
+                performanceId: row.performanceId
+            };
             this.$http
-                .post('/programmeScore/saveScore?programmeId=' + row.id, {
-                    score: row.myScore,
-                    remark: row.remark,
-                    performanceId: row.performanceId
-                })
+                .post('/programmeScore/saveScore', record, { body: 'json' })
                 .then(res => {
                     this.$message.success('评分成功');
                     this.getData();