licailing 4 лет назад
Родитель
Сommit
afa9b575c0

+ 2 - 0
src/main/java/com/izouma/wenlvju/repo/performance/ProgrammeScoreRepo.java

@@ -22,6 +22,8 @@ public interface ProgrammeScoreRepo extends JpaRepository<ProgrammeScore, Long>,
 
     List<ProgrammeScore> findAllByProgrammeId(Long programmeId);
 
+    List<ProgrammeScore> findAllByProgrammeIdIn(Collection<Long> programmeId);
+
     @Query("select avg(score) from ProgrammeScore where programmeId = ?1")
     Object avgScore(Long programmeId);
 

+ 37 - 21
src/main/java/com/izouma/wenlvju/service/performance/ProgrammeService.java

@@ -11,7 +11,10 @@ import com.izouma.wenlvju.config.DateConfig;
 import com.izouma.wenlvju.domain.*;
 import com.izouma.wenlvju.domain.performance.*;
 import com.izouma.wenlvju.dto.*;
-import com.izouma.wenlvju.enums.*;
+import com.izouma.wenlvju.enums.CompetitionGroup;
+import com.izouma.wenlvju.enums.PerformanceStatus;
+import com.izouma.wenlvju.enums.ProgrammeStatus;
+import com.izouma.wenlvju.enums.SignedIn;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.repo.*;
 import com.izouma.wenlvju.repo.performance.*;
@@ -29,8 +32,6 @@ import org.apache.poi.util.TempFile;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
 import org.springframework.stereotype.Service;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.persistence.criteria.Predicate;
@@ -41,7 +42,6 @@ import java.io.*;
 import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -165,7 +165,6 @@ public class ProgrammeService {
         dto.setGradingOrganization(gradingOrganization);
         dto.setSpecialty(artType);
         dto.setLevel(setting);
-//        dto.setQuantity(participant);
         return dto;
     }
 
@@ -648,18 +647,12 @@ public class ProgrammeService {
         return dto;
     }
 
-    public Page<ProgrammeScoreDTO> byExpert(PageQuery pageQuery, Long userId) {
-        pageQuery.setSort("showBegin,asc;");
-        Long arrangeId = Convert.convert(Long.class, pageQuery.getQuery().get("arrangeId"));
-        return this.toDTOPage(this.all(pageQuery), Collections.singletonList(arrangeId), userId);
-    }
-
     public Page<ProgrammeScoreDTO> byScore(PageQuery pageQuery, Long userId) {
         List<Long> arrangeId = arrangeJudgeRepo.findArrangeIdByExpertId(userId);
         if (CollUtil.isEmpty(arrangeId)) {
             return new PageImpl<>(new ArrayList<>(), JpaUtils.toPageRequest(pageQuery), 0);
         }
-        pageQuery.setSort("allScore,asc;showBegin,asc;arrangeId,asc;");
+        pageQuery.setSort("allScore,asc;arrangeId,asc;showBegin,asc;");
         Page<Programme> all = programmeRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
             List<Predicate> and = JpaUtils.toPredicates(pageQuery, Programme.class, root, criteriaQuery, criteriaBuilder);
             and.add(root.get("arrangeId").in(arrangeId));
@@ -669,7 +662,38 @@ public class ProgrammeService {
         return this.toDTOPage(all, arrangeId, userId);
     }
 
-    private Page<ProgrammeScoreDTO> toDTOPage(Page<Programme> all, Collection<Long> arrangeId, Long userId) {
+    public Page<ProgrammeScoreDTO> toDTOPage(Page<Programme> all) {
+        List<Long> ids = all.getContent().stream().map(Programme::getId).distinct().collect(Collectors.toList());
+        Map<Long, List<Participant>> participantMap = participantRepo.findAllByProgrammeIdIn(ids)
+                .stream()
+                .collect(Collectors.groupingBy(Participant::getProgrammeId));
+        Map<Long, String> artTypeMap = artTypeRepo.findAll()
+                .stream()
+                .collect(Collectors.toMap(ArtType::getId, ArtType::getName));
+
+        Map<Long, String> arrangeMap = arrangeRepo.findAllByPerformanceId(all.getContent().get(0).getPerformanceId())
+                .stream()
+                .collect(Collectors.toMap(Arrange::getId, Arrange::getName));
+
+        Map<Long, Double> scoreMap = programmeScoreRepo.findAllByProgrammeIdIn(ids)
+                .stream()
+                .collect(Collectors.groupingBy(ProgrammeScore::getProgrammeId, Collectors.averagingDouble(ProgrammeScore::getScore)));
+
+        return all.map(programme -> {
+            ProgrammeScoreDTO dto = new ProgrammeScoreDTO(programme);
+            dto.setSpecialty(artTypeMap.get(programme.getSpecialtyId()));
+            dto.setArrangeName(arrangeMap.get(programme.getArrangeId()));
+            dto.setMyScore(scoreMap.get(programme.getId()));
+            List<String> participants = participantMap.get(programme.getId())
+                    .stream()
+                    .map(Participant::getName)
+                    .collect(Collectors.toList());
+            dto.setParticipant(participants);
+            return dto;
+        });
+    }
+
+    public Page<ProgrammeScoreDTO> toDTOPage(Page<Programme> all, Collection<Long> arrangeId, Long userId) {
         List<Long> ids = all.getContent().stream().map(Programme::getId).distinct().collect(Collectors.toList());
         Map<Long, List<Participant>> participantMap = participantRepo.findAllByProgrammeIdIn(ids)
                 .stream()
@@ -721,14 +745,6 @@ public class ProgrammeService {
                 .build());
     }
 
-    /*
-    考级机构显示节目详情
-     */
-    public ProgrammeShowDTO showByGO(Long id) {
-        Programme programme = programmeRepo.findById(id).orElseThrow(new BusinessException("无节目"));
-        return this.toShowDTO(programme);
-    }
-
     public ProgrammeShowDTO toShowDTO(Programme programme) {
         ProgrammeShowDTO dto = new ProgrammeShowDTO(programme);
         List<ParticipantDTO> participants = participantRepo.findAllByProgrammeId(programme.getId())

+ 24 - 5
src/main/java/com/izouma/wenlvju/web/performance/ProgrammeController.java

@@ -1,11 +1,11 @@
 package com.izouma.wenlvju.web.performance;
 
+import cn.hutool.core.convert.Convert;
 import com.izouma.wenlvju.domain.performance.Programme;
 import com.izouma.wenlvju.dto.*;
 import com.izouma.wenlvju.enums.ProgrammeStatus;
 import com.izouma.wenlvju.enums.SignedIn;
 import com.izouma.wenlvju.exception.BusinessException;
-import com.izouma.wenlvju.repo.performance.PerformanceRepo;
 import com.izouma.wenlvju.repo.performance.ProgrammeRepo;
 import com.izouma.wenlvju.service.UserService;
 import com.izouma.wenlvju.service.performance.ProgrammeService;
@@ -16,11 +16,13 @@ import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 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;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -32,7 +34,6 @@ public class ProgrammeController extends BaseController {
     private ProgrammeService programmeService;
     private ProgrammeRepo    programmeRepo;
     private UserService      userService;
-    private PerformanceRepo  performanceRepo;
 
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
@@ -40,6 +41,13 @@ public class ProgrammeController extends BaseController {
         return programmeService.save(record, SecurityUtils.getAuthenticatedUser().getId());
     }
 
+    @PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/saveScore")
+    public Programme saveScore(@RequestParam Long id, @RequestParam Double score) {
+        Programme programme = programmeRepo.findById(id).orElseThrow(new BusinessException("无节目"));
+        programme.setScore(score);
+        return programmeRepo.save(programme);
+    }
 
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/all")
@@ -119,16 +127,26 @@ public class ProgrammeController extends BaseController {
     @PostMapping("/byExpert")
     @ApiOperation("专家手机端查看")
     public Page<ProgrammeScoreDTO> byExpert(@RequestBody PageQuery pageQuery) {
-        return programmeService.byExpert(pageQuery, SecurityUtils.getAuthenticatedUser().getId());
+        pageQuery.setSort("showBegin,asc;");
+        Long arrangeId = Convert.convert(Long.class, pageQuery.getQuery().get("arrangeId"));
+        return programmeService.toDTOPage(this.all(pageQuery), Collections.singletonList(arrangeId), SecurityUtils.getAuthenticatedUser()
+                .getId());
     }
 
-
     @PostMapping("/byScore")
     @ApiOperation("专家电脑端查看")
     public Page<ProgrammeScoreDTO> byScore(@RequestBody PageQuery pageQuery) {
         return programmeService.byScore(pageQuery, SecurityUtils.getAuthenticatedUser().getId());
     }
 
+    @PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/byScoreAdmin")
+    @ApiOperation("查看分数")
+    public Page<ProgrammeScoreDTO> byScoreAdmin(@RequestBody PageQuery pageQuery) {
+        Page<Programme> all = this.all(pageQuery);
+        return programmeService.toDTOPage(all);
+    }
+
     @PostMapping("/getDTO/{id}")
     @ApiOperation("专家手机端查看详情")
     public ProgrammeScoreDTO getDTO(@PathVariable Long id) {
@@ -144,7 +162,8 @@ public class ProgrammeController extends BaseController {
     @GetMapping("/getShow/{id}")
     @ApiOperation("考级机构查看节目信息")
     public ProgrammeShowDTO getShow(@PathVariable Long id) {
-        return programmeService.showByGO(id);
+        Programme programme = programmeRepo.findById(id).orElseThrow(new BusinessException("无节目"));
+        return programmeService.toShowDTO(programme);
     }
 
     @ApiOperation("获取手机号/token")

+ 0 - 30
src/main/vue/src/components/ProgrammeLog.vue

@@ -457,36 +457,6 @@ export default {
                     console.log(e);
                 });
         },
-        onSave() {
-            this.$refs.form.validate(valid => {
-                if (valid) {
-                    this.submit();
-                } else {
-                    return false;
-                }
-            });
-        },
-        submit() {
-            let data = { ...this.formData };
-            this.saving = true;
-            this.$http
-                .post('/programme/save', data, { body: 'json' })
-                .then(res => {
-                    this.saving = false;
-
-                    this.programmeId = res.id;
-                    this.$nextTick(() => {
-                        this.$http.post('/participant/batchSave', this.saveOtherJson, { body: 'json' });
-                    });
-                    this.$message.success('成功');
-                    this.$router.go(-1);
-                })
-                .catch(e => {
-                    console.log(e);
-                    this.saving = false;
-                    this.$message.error(e.error);
-                });
-        },
         onDelete() {
             this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
                 .then(() => {

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

@@ -692,6 +692,17 @@ const router = new Router({
                         title: '节目评审'
                     }
                 },
+                {
+                    path: '/progScoreAdminList',
+                    name: 'ProgScoreAdminList',
+                    component: () =>
+                        import(
+                            /* webpackChunkName: "progScoreAdminList" */ '@/views/performance/ProgScoreAdminList.vue'
+                        ),
+                    meta: {
+                        title: '得分列表'
+                    }
+                },
                 {
                     path: '/participantEdit',
                     name: 'ParticipantEdit',

+ 505 - 0
src/main/vue/src/views/performance/ProgScoreAdminList.vue

@@ -0,0 +1,505 @@
+<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-form-item>
+                            <el-button>设置复审</el-button>
+                        </el-form-item>
+                    </el-col>
+                    <!-- <div v-if="!performance.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"
+        >
+            <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
+            <el-table-column prop="id" label="编号" width="80"> </el-table-column>
+            <el-table-column prop="arrangeName" label="分组"> </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.join(',') }}</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="!performance.online">
+            </el-table-column>
+            <el-table-column prop="myScore" label="专家平均分"> </el-table-column>
+            <el-table-column prop="score" label="成绩">
+                <template slot-scope="{ row }">
+                    <span v-if="!row.second">{{ row.score }}</span>
+                    <el-input-number
+                        v-else
+                        v-model="row.score"
+                        size="mini"
+                        label=""
+                        :min="0"
+                        :max="100"
+                        :step="1"
+                        :controls="true"
+                        controls-position="right"
+                        @change="saveRow(row)"
+                        style="width: 80px"
+                    >
+                    </el-input-number>
+                </template>
+            </el-table-column>
+            <el-table-column label="操作" align="left" fixed="right" min-width="150">
+                <template slot-scope="{ row, $index }">
+                    <el-button @click="playVideo(row, $index)" size="mini" plain type="primary">查看作品</el-button>
+                    <el-button @click="row.second = true" size="mini" plain type="warning" v-if="!row.second"
+                        >修改</el-button
+                    >
+                    <el-button @click="row.second = false" size="mini" plain type="danger" v-else>取消</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="70%">
+            <video :src="programme.video" controls style="height: 85%; max-width: 85%; margin: 0 auto">
+                您的浏览器不支持 video 标签。
+            </video>
+            <el-card shadow="never" style="width: 85%; margin: 10px auto">
+                <el-form :form="programme">
+                    <el-form-item label="分数">
+                        <span v-if="!programme.second">{{ programme.score }}</span>
+                        <el-input-number
+                            v-else
+                            v-model="programme.score"
+                            size="mini"
+                            label=""
+                            :min="0"
+                            :max="100"
+                            :step="1"
+                            :controls="true"
+                            controls-position="both"
+                        >
+                        </el-input-number>
+                    </el-form-item>
+                    <el-form-item>
+                        <el-button size="mini" v-if="!programme.second" @click="programme.second = true" type="warning"
+                            >修改</el-button
+                        >
+                        <el-button size="mini" v-else @click="saveRow(programme)" type="primary">保存</el-button>
+                        <el-button
+                            @click="programme.second = false"
+                            size="mini"
+                            plain
+                            type="danger"
+                            v-if="programme.second"
+                            >取消</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"
+                            >下一个</el-button
+                        >
+                    </el-form-item>
+                </el-form>
+            </el-card>
+        </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: 'ProgScoreAdminList',
+    mixins: [pageableTable, delChild],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/programme/byScoreAdmin',
+            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
+        };
+    },
+    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.performanceId = res.content[0].id;
+                    this.performance = 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 = {
+                sort: 'score,desc',
+                query: {}
+            };
+            if (this.performanceId) {
+                data.query.performanceId = this.performanceId;
+            }
+            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();
+                })
+                .catch(e => {
+                    this.$message.error(e.error);
+                });
+        },
+        saveRow(row) {
+            if (!row.score) {
+                this.$message.warning('请输入评分');
+                return;
+            }
+            this.$http
+                .post('/programme/saveScore', {
+                    id: row.id,
+                    score: row.score
+                })
+                .then(res => {
+                    this.saving = false;
+                    this.$message.success('成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.saving = false;
+                    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;
+            if (row.video) {
+                this.showViedo = true;
+                this.programme = row;
+            } else {
+                this.$message.success('暂无视频');
+            }
+        },
+        move(direction) {
+            const end = direction + this.index;
+            this.programme = { ...this.tableData[end] };
+            this.index = end;
+        }
+    }
+};
+</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>

+ 5 - 2
src/main/vue/src/views/performance/ProgrammeList.vue

@@ -290,7 +290,7 @@
         </el-dialog>
         <programme-log :dialogVisible="isShow" @close="isShow = false" ref="public"></programme-log>
         <el-dialog class="videoDialog" destroy-on-close center append-to-body :visible.sync="showImg" width="35%">
-            <img style="height: 100%; max-width: 100%" :src="annex" alt="" />
+            <img style="height: 100%; max-width: 100%;" :src="annex" alt="" />
         </el-dialog>
     </div>
 </template>
@@ -635,8 +635,11 @@ export default {
             if (row.video) {
                 this.showViedo = true;
                 this.videoUrl = row.video;
+            } else if (row.annex) {
+                this.showImg = true;
+                this.annex = row.annex;
             } else {
-                this.$message.success('暂无视频');
+                this.$message.success('暂无作品');
             }
         },
         playImg(row) {

+ 2 - 1
src/main/vue/src/views/performance/ProgrammeScoreList.vue

@@ -134,10 +134,11 @@
             </el-pagination>
         </div>
 
-        <el-dialog class="videoDialog" destroy-on-close center append-to-body :visible.sync="showViedo" width="70%">
+        <el-dialog class="videoDialog" destroy-on-close center append-to-body :visible.sync="showViedo" width="60%">
             <video :src="programme.video" controls style="height: 85%; max-width: 85%; margin: 0 auto">
                 您的浏览器不支持 video 标签。
             </video>
+            <img style="height: 100%; max-width: 100%" :src="programme.annex" alt="" />
             <el-card shadow="never" style="width: 85%; margin: 10px auto">
                 <el-form :form="programme">
                     <el-form-item label="分数">

+ 0 - 31
src/main/vue/src/views/performance/ProgrammeShow.vue

@@ -426,37 +426,6 @@ export default {
         }
     },
     methods: {
-        onSave() {
-            this.$refs.form.validate(valid => {
-                if (valid) {
-                    this.submit();
-                } else {
-                    return false;
-                }
-            });
-        },
-        submit() {
-            let data = { ...this.formData };
-
-            this.saving = true;
-            this.$http
-                .post('/programme/save', data, { body: 'json' })
-                .then(res => {
-                    this.saving = false;
-
-                    this.programmeId = res.id;
-                    this.$nextTick(() => {
-                        this.$http.post('/participant/batchSave', this.saveOtherJson, { body: 'json' });
-                    });
-                    this.$message.success('成功');
-                    this.$router.go(-1);
-                })
-                .catch(e => {
-                    console.log(e);
-                    this.saving = false;
-                    this.$message.error(e.error);
-                });
-        },
         onDelete() {
             this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
                 .then(() => {

+ 1 - 1
src/test/java/com/izouma/wenlvju/repo/UserRepoTest.java

@@ -74,7 +74,7 @@ public class UserRepoTest {
 
     @Test
     public void test3() {
-        System.out.println(jwtTokenUtil.generateToken(JwtUserFactory.create(userRepo.findById(348L)
+        System.out.println(jwtTokenUtil.generateToken(JwtUserFactory.create(userRepo.findById(300L)
                 .orElseThrow(new BusinessException("用户不存在")))));
     }