Просмотр исходного кода

Merge branch 'test' of http://git.izouma.com/licailing/wenlvju into test

 Conflicts:
	src/main/java/com/izouma/wenlvju/service/performance/ProgrammeService.java
	src/main/java/com/izouma/wenlvju/utils/FileUtils.java
	src/main/resources/application.yaml
	src/main/vue/src/views/performance/ProgrammeOrgList.vue
	src/main/vue/src/views/user/UserList.vue
	src/test/java/com/izouma/wenlvju/repo/UserRepoTest.java
xuqiang 4 лет назад
Родитель
Сommit
ff85d32086
80 измененных файлов с 4673 добавлено и 664 удалено
  1. 12 0
      pom.xml
  2. 1 1
      src/main/h5/public/index.html
  3. 2 2
      src/main/h5/src/plugins/http.js
  4. 5 0
      src/main/h5/src/router/index.js
  5. 41 2
      src/main/h5/src/views/Home.vue
  6. 674 0
      src/main/h5/src/views/TrainingInstitution.vue
  7. 49 42
      src/main/h5/src/views/loginHome.vue
  8. 30 0
      src/main/java/com/izouma/wenlvju/domain/Announcement.java
  9. 2 0
      src/main/java/com/izouma/wenlvju/domain/Rate.java
  10. 152 0
      src/main/java/com/izouma/wenlvju/domain/TrainingInstitution.java
  11. 2 0
      src/main/java/com/izouma/wenlvju/domain/performance/Participant.java
  12. 2 0
      src/main/java/com/izouma/wenlvju/domain/performance/Performance.java
  13. 25 18
      src/main/java/com/izouma/wenlvju/dto/ProgrammeShowDTO.java
  14. 2 0
      src/main/java/com/izouma/wenlvju/dto/RateDTO.java
  15. 45 0
      src/main/java/com/izouma/wenlvju/dto/TrainingInstitutionDTO.java
  16. 12 0
      src/main/java/com/izouma/wenlvju/enums/AnnouncementType.java
  17. 26 0
      src/main/java/com/izouma/wenlvju/enums/GradingOrganizationDTO.java
  18. 16 0
      src/main/java/com/izouma/wenlvju/repo/AnnouncementRepo.java
  19. 3 0
      src/main/java/com/izouma/wenlvju/repo/RateRepo.java
  20. 30 0
      src/main/java/com/izouma/wenlvju/repo/TrainingInstitutionRepo.java
  21. 7 0
      src/main/java/com/izouma/wenlvju/repo/performance/ParticipantRepo.java
  22. 4 0
      src/main/java/com/izouma/wenlvju/security/WebSecurityConfig.java
  23. 20 0
      src/main/java/com/izouma/wenlvju/service/AnnouncementService.java
  24. 19 25
      src/main/java/com/izouma/wenlvju/service/RateExpertAuditService.java
  25. 211 22
      src/main/java/com/izouma/wenlvju/service/RateService.java
  26. 98 0
      src/main/java/com/izouma/wenlvju/service/TrainingInstitutionService.java
  27. 25 0
      src/main/java/com/izouma/wenlvju/service/UserService.java
  28. 23 0
      src/main/java/com/izouma/wenlvju/service/performance/ParticipantService.java
  29. 184 119
      src/main/java/com/izouma/wenlvju/service/performance/ProgrammeService.java
  30. 30 0
      src/main/java/com/izouma/wenlvju/service/storage/AliStorageService.java
  31. 116 31
      src/main/java/com/izouma/wenlvju/utils/FileUtils.java
  32. 60 0
      src/main/java/com/izouma/wenlvju/web/AnnouncementController.java
  33. 11 1
      src/main/java/com/izouma/wenlvju/web/AuthenticationController.java
  34. 6 3
      src/main/java/com/izouma/wenlvju/web/GradingOrganizationController.java
  35. 16 2
      src/main/java/com/izouma/wenlvju/web/RateController.java
  36. 1 1
      src/main/java/com/izouma/wenlvju/web/RateExpertAuditController.java
  37. 102 0
      src/main/java/com/izouma/wenlvju/web/TrainingInstitutionController.java
  38. 29 7
      src/main/java/com/izouma/wenlvju/web/performance/ProgrammeController.java
  39. 3 6
      src/main/resources/application.yaml
  40. 1 0
      src/main/resources/genjson/Announcement.json
  41. 0 0
      src/main/resources/genjson/TrainingInstitution.json
  42. 0 0
      src/main/resources/templates/RateTemplate.ftl
  43. 1 0
      src/main/vue/package.json
  44. 5 1
      src/main/vue/src/components/OrganizationLog.vue
  45. 3 0
      src/main/vue/src/components/ProgrammeLog.vue
  46. 328 0
      src/main/vue/src/components/ProgrammeLog1.vue
  47. 6 3
      src/main/vue/src/components/RichText.vue
  48. 2 0
      src/main/vue/src/main.js
  49. 1 0
      src/main/vue/src/mixins/pageableTable.js
  50. 53 1
      src/main/vue/src/router.js
  51. 94 0
      src/main/vue/src/views/AnnouncementDetail.vue
  52. 106 0
      src/main/vue/src/views/AnnouncementEdit.vue
  53. 169 0
      src/main/vue/src/views/AnnouncementList.vue
  54. 12 6
      src/main/vue/src/views/Dashboard.vue
  55. 26 13
      src/main/vue/src/views/Login.vue
  56. 180 0
      src/main/vue/src/views/TrainingInstitutionEdit.vue
  57. 279 0
      src/main/vue/src/views/TrainingInstitutionList.vue
  58. 1 0
      src/main/vue/src/views/performance/ArrangeJudgeList.vue
  59. 3 1
      src/main/vue/src/views/performance/PerformanceEdit.vue
  60. 13 4
      src/main/vue/src/views/performance/ProgrammeEdit.vue
  61. 388 0
      src/main/vue/src/views/performance/ProgrammeGOList.vue
  62. 255 129
      src/main/vue/src/views/performance/ProgrammeList.vue
  63. 126 34
      src/main/vue/src/views/performance/ProgrammeOrgList.vue
  64. 3 7
      src/main/vue/src/views/performance/ProgrammeScoreList.vue
  65. 7 24
      src/main/vue/src/views/rate/RateDistrictList.vue
  66. 2 30
      src/main/vue/src/views/rate/RateDistrictListDone.vue
  67. 10 24
      src/main/vue/src/views/rate/RateDistrictListPending.vue
  68. 3 62
      src/main/vue/src/views/rate/RateList.vue
  69. 35 1
      src/main/vue/src/views/rate/RateListDone.vue
  70. 56 1
      src/main/vue/src/views/rate/RateListPending.vue
  71. 49 6
      src/main/vue/src/views/rate/RateOrganizerList.vue
  72. 0 1
      src/main/vue/src/views/user/UserList.vue
  73. 103 0
      src/main/vue/src/widgets/BoardWidget.vue
  74. 101 0
      src/main/vue/src/widgets/PolicyWidget.vue
  75. 16 0
      src/main/vue/yarn.lock
  76. 13 2
      src/test/java/com/izouma/wenlvju/repo/RepoTest.java
  77. 1 1
      src/test/java/com/izouma/wenlvju/repo/UserRepoTest.java
  78. 60 28
      src/test/java/com/izouma/wenlvju/service/RateServiceTest.java
  79. 5 3
      src/test/java/com/izouma/wenlvju/service/sms/NjwlSmsServiceTest.java
  80. 61 0
      src/test/java/com/izouma/wenlvju/web/TrainingInstitutionControllerTest.java

+ 12 - 0
pom.xml

@@ -304,6 +304,18 @@
             <artifactId>jave-all-deps</artifactId>
             <artifactId>jave-all-deps</artifactId>
             <version>3.1.1</version>
             <version>3.1.1</version>
         </dependency>
         </dependency>
+
+        <!-- 解压rar -->
+        <dependency>
+            <groupId>com.github.junrar</groupId>
+            <artifactId>junrar</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.11.2</version>
+        </dependency>
     </dependencies>
     </dependencies>
 
 
 </project>
 </project>

+ 1 - 1
src/main/h5/public/index.html

@@ -5,7 +5,7 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
-    <title><%= htmlWebpackPlugin.options.title %></title>
+    <title>宁艺通</title>
   </head>
   </head>
   <body>
   <body>
     <noscript>
     <noscript>

+ 2 - 2
src/main/h5/src/plugins/http.js

@@ -4,9 +4,9 @@ import qs from "qs";
 let baseUrl = "http://localhost:8080";
 let baseUrl = "http://localhost:8080";
 switch (process.env.NODE_ENV) {
 switch (process.env.NODE_ENV) {
   case "development":
   case "development":
+    baseUrl = "http://yskj.njlyw.cn:8081";
     // baseUrl = "http://wljtest.izouma.com";
     // baseUrl = "http://wljtest.izouma.com";
-    baseUrl = "http://localhost:8080";
-    // baseUrl = 'http://192.168.50.190:8080';
+    // baseUrl = 'http://localhost:8080';
     break;
     break;
   case "test":
   case "test":
     baseUrl = "http://localhost:8080";
     baseUrl = "http://localhost:8080";

+ 5 - 0
src/main/h5/src/router/index.js

@@ -14,6 +14,11 @@ const routes = [
     name: "home",
     name: "home",
     component: () => import("../views/Home.vue")
     component: () => import("../views/Home.vue")
   },
   },
+  {
+    path: "/trainingInstitution",
+    name: "trainingInstitution",
+    component: () => import("../views/TrainingInstitution.vue")
+  },
   {
   {
     path: "/login",
     path: "/login",
     name: "login",
     name: "login",

+ 41 - 2
src/main/h5/src/views/Home.vue

@@ -19,6 +19,18 @@
     <div style="margin-top:20px" v-if="info.video">
     <div style="margin-top:20px" v-if="info.video">
       <video-upload v-model="info2" class="width"></video-upload>
       <video-upload v-model="info2" class="width"></video-upload>
     </div>
     </div>
+    <div style="margin-top:20px" v-else-if="info.annex">
+      <van-image
+        fit="cover"
+        style="padding:0 16px"
+        v-for="(a, index) in list"
+        :key="index"
+        @click="preview(index, a)"
+        :src="a"
+        width="92%"
+        height="150px"
+      />
+    </div>
     <div class="base">
     <div class="base">
       <div class="base-info">
       <div class="base-info">
         <div class="base-info-item">
         <div class="base-info-item">
@@ -29,9 +41,29 @@
           <div class="text1">专业</div>
           <div class="text1">专业</div>
           <div class="text2">{{ info.specialty }}</div>
           <div class="text2">{{ info.specialty }}</div>
         </div>
         </div>
+        <div class="base-info-item">
+          <div class="text1">节目状态</div>
+          <div class="text2" v-if="info.programmeStatus == 'SUBMIT'">
+            审核中
+          </div>
+          <div class="text2" v-else-if="info.programmeStatus == 'AUDIT_FAILED'">
+            考级机构审核未通过
+          </div>
+          <div
+            class="text2"
+            v-else-if="info.programmeStatus == 'REVIEW_FAILED'"
+          >
+            审核未通过
+          </div>
+          <div class="text2" v-else>未提交</div>
+        </div>
+      </div>
+      <div class="base-info">
+        <img class="left-icon icon" src="../assets/icon_lianjie.png" alt="" />
+        <img class="right-icon icon" src="../assets/icon_lianjie.png" alt="" />
         <div v-for="(time, index) in info.participants" :key="index">
         <div v-for="(time, index) in info.participants" :key="index">
           <div class="base-info-item">
           <div class="base-info-item">
-            <div class="text1">参演时间</div>
+            <div class="text1">出生日期</div>
             <div class="text2">
             <div class="text2">
               {{ time.birthday }}
               {{ time.birthday }}
             </div>
             </div>
@@ -89,7 +121,7 @@
           </div>
           </div>
         </div>
         </div>
       </div> -->
       </div> -->
-      <div class="base-info">
+      <div class="base-info" v-if="info.score">
         <img class="left-icon icon" src="../assets/icon_lianjie.png" alt="" />
         <img class="left-icon icon" src="../assets/icon_lianjie.png" alt="" />
         <img class="right-icon icon" src="../assets/icon_lianjie.png" alt="" />
         <img class="right-icon icon" src="../assets/icon_lianjie.png" alt="" />
         <div class="score">
         <div class="score">
@@ -171,6 +203,7 @@
 
 
 <script>
 <script>
 import { mapState } from "vuex";
 import { mapState } from "vuex";
+import { ImagePreview } from "vant";
 // import QrcodeVue from "qrcode.vue";
 // import QrcodeVue from "qrcode.vue";
 export default {
 export default {
   name: "home",
   name: "home",
@@ -185,6 +218,7 @@ export default {
       info: {},
       info: {},
       info2: {},
       info2: {},
       persons: [],
       persons: [],
+      list: [],
       isAdmin: false,
       isAdmin: false,
       scores: [],
       scores: [],
       score: "",
       score: "",
@@ -244,6 +278,9 @@ export default {
     // this.getInfo();
     // this.getInfo();
   },
   },
   methods: {
   methods: {
+    preview(index = 0, list = []) {
+      ImagePreview([list]);
+    },
     next() {
     next() {
       this.nowActive = this.nowActive + 1;
       this.nowActive = this.nowActive + 1;
       this.persons = [];
       this.persons = [];
@@ -275,6 +312,8 @@ export default {
         })
         })
         .then(res => {
         .then(res => {
           this.info = res;
           this.info = res;
+          this.list = { src: res.annex };
+          // console.log(this.list);
           this.info2 = {
           this.info2 = {
             src: this.info.video
             src: this.info.video
           };
           };

+ 674 - 0
src/main/h5/src/views/TrainingInstitution.vue

@@ -0,0 +1,674 @@
+<template>
+  <div class="page">
+    <van-form ref="form" @submit="submit" :submit-on-enter="false">
+      <van-popover v-model="showPopover" trigger="click">
+        <template #reference>
+          <van-field
+            name="企业名称"
+            label="企业名称"
+            placeholder="请输入企业名称"
+            v-model="form.name"
+            :rules="[{ required: true, message: '请填写企业名称' }]"
+            @change="like"
+          />
+        </template>
+
+        <van-cell-group>
+          <van-cell
+            v-for="(item, index) in list"
+            :key="index"
+            :title="item"
+            @click="choose(item)"
+          />
+        </van-cell-group>
+      </van-popover>
+      <van-field
+        name="注册号"
+        label="注册号/统一社会信用代码"
+        placeholder="请输入注册号/统一社会信用代码"
+        v-model="form.uscc"
+        :rules="[{ required: true, message: '请填写注册号/统一社会信用代码' }]"
+      />
+      <van-field
+        name="是否从事文化艺术类校外培训"
+        label="是否从事文化艺术类校外培训"
+        :rules="[
+          {
+            validator: val => {
+              return val || val === false;
+            },
+            message: '请选择'
+          }
+        ]"
+      >
+        <template #input>
+          <van-radio-group
+            v-model="form.engagedInTraining"
+            direction="horizontal"
+          >
+            <van-radio :name="true"> 是</van-radio>
+            <van-radio :name="false">否</van-radio>
+          </van-radio-group>
+        </template>
+      </van-field>
+      <div style="margin:30px" v-if="!form.id">
+        <van-button
+          class="submit"
+          native-type="button"
+          round
+          block
+          type="info"
+          @click="byUscc"
+        >
+          查询
+        </van-button>
+      </div>
+      <template v-else-if="form.engagedInTraining">
+        <van-field
+          type="textarea"
+          name="经营范围"
+          label="经营范围"
+          placeholder="请输入经营范围"
+          v-model="form.businessScope"
+          autosize
+        />
+        <van-field
+          name="企业住所"
+          label="企业住所"
+          placeholder="请输入企业住所"
+          v-model="form.address"
+        />
+        <van-field
+          name="生产经营场所"
+          label="生产经营场所"
+          placeholder="请输入生产经营场所"
+          v-model="form.businessPremise"
+        />
+        <van-field
+          name="生产法人姓名"
+          label="生产法人姓名"
+          placeholder="请输入生产法人姓名"
+          v-model="form.privacyPolicy"
+        />
+        <!-- <van-field
+          type="tel"
+          maxlength="11"
+          name="生产短信号码"
+          label="生产短信号码"
+          placeholder="请输入短信号码"
+          v-model="form.phone"
+        /> -->
+        <van-field
+          type="digit"
+          name="企业联系方式"
+          label="企业联系方式"
+          placeholder="请输入企业联系方式"
+          v-model="form.contactPhone"
+        />
+        <van-field
+          name="所属管区"
+          label="所属管区"
+          placeholder="请输入所属管区"
+          v-model="form.district"
+        />
+        <van-field
+          type="number"
+          name="注册资本"
+          label="注册资本(万)"
+          placeholder="请输入注册资本"
+          v-model="form.registeredCapital"
+        />
+        <van-field
+          name="单位性质"
+          label="单位性质"
+          placeholder="请输入单位性质"
+          v-model="form.category"
+          readonly
+          @click="showType = true"
+        />
+
+        <van-action-sheet
+          v-model="showType"
+          :actions="types"
+          cancel-text="取消"
+          close-on-click-action
+          @select="onSelect"
+        />
+        <!-- <van-popup v-model="showArea" position="bottom">
+  <van-area
+    :area-list="areaList"
+    @confirm="onConfirm"
+    @cancel="showArea = false"
+  />
+</van-popup> -->
+
+        <van-field
+          name="专业种类"
+          label="专业种类"
+          placeholder="请输入专业种类"
+        >
+          <template #input>
+            <van-checkbox-group v-model="form.specialty" direction="horizontal">
+              <van-checkbox
+                :name="item"
+                v-for="(item, index) in specialtyOptions"
+                :key="index"
+                >{{ item }}</van-checkbox
+              >
+              <div class="extra-content">
+                <van-checkbox class="extra" name="其他">其他</van-checkbox>
+                <van-field
+                  v-if="showExtra"
+                  class="input"
+                  type="text"
+                  placeholder="请输入"
+                  v-model="extra"
+                  size="small"
+                />
+              </div>
+            </van-checkbox-group>
+          </template>
+        </van-field>
+        <van-field
+          type="digit"
+          name="培训点数量三楼及以下"
+          label="培训点数量三楼及以下"
+          placeholder="请输入培训点数量三楼及以下"
+          v-model="form.trainingSite"
+        />
+        <van-field
+          type="digit"
+          name="培训点数量四楼及以上"
+          label="培训点数量四楼及以上"
+          placeholder="请输入培训点数量四楼及以上"
+          v-model="form.trainingSiteFour"
+        />
+        <van-field
+          type="number"
+          name="总面积"
+          label="总面积(建筑面积)"
+          placeholder="请输入总面积(建筑面积)"
+          v-model="form.area"
+        />
+        <van-field
+          type="digit"
+          name="教室数量"
+          label="教室数量"
+          placeholder="请输入教室数量"
+          v-model="form.classroomNum"
+          :rules="[{ required: true, message: '请填写教室数量' }]"
+        />
+
+        <div class="panel">
+          <van-divider content-position="left">教师人数统计</van-divider>
+          <van-field
+            type="digit"
+            name="专职数量"
+            label="专职数量"
+            placeholder="请输入专职数量"
+            v-model="form.fullTimeNum"
+            @change="changeNum"
+            :rules="[{ required: true, message: '请填写专职数量' }]"
+          />
+          <van-field
+            type="digit"
+            name="兼职数量"
+            label="兼职数量"
+            placeholder="请输入兼职数量"
+            v-model="form.partTimeNum"
+            @change="changeNum"
+            :rules="[{ required: true, message: '请填写兼职数量' }]"
+          />
+          <van-field
+            type="digit"
+            name="教师总数"
+            label="教师总数"
+            placeholder="请输入教师总数"
+            v-model="form.teacherNum"
+            :rules="[{ required: true, message: '请填写教师总数' }]"
+          />
+        </div>
+        <div class="panel">
+          <van-divider content-position="left">教师专业人数统计</van-divider>
+
+          <van-field
+            type="digit"
+            name="音乐类"
+            label="音乐类"
+            placeholder="请输入音乐类"
+            v-model="form.musicNum"
+            @focus="focusNum('musicNum')"
+            @blur="blurNum('musicNum')"
+            @input="changeClass($event, 'musicNum')"
+            :rules="[
+              {
+                validator: val => {
+                  return !isMore;
+                },
+                message: '教师总数为' + form.teacherNum
+              }
+            ]"
+          />
+          <van-field
+            type="digit"
+            name="舞蹈类"
+            label="舞蹈类"
+            placeholder="请输入舞蹈类"
+            v-model="form.danceNum"
+            @focus="focusNum('danceNum')"
+            @blur="blurNum('danceNum')"
+            @input="changeClass($event, 'danceNum')"
+            :rules="[
+              {
+                validator: val => {
+                  return !isMore;
+                },
+                message: '教师总数为' + form.teacherNum
+              }
+            ]"
+          />
+          <van-field
+            type="digit"
+            name="美术类"
+            label="美术类"
+            placeholder="请输入美术类"
+            v-model="form.artNum"
+            @focus="focusNum('artNum')"
+            @blur="blurNum('artNum')"
+            @input="changeClass($event, 'artNum')"
+            :rules="[
+              {
+                validator: val => {
+                  return !isMore;
+                },
+                message: '教师总数为' + form.teacherNum
+              }
+            ]"
+          />
+          <van-field
+            type="digit"
+            name="戏剧戏曲"
+            label="戏剧戏曲"
+            placeholder="请输入戏剧戏曲"
+            v-model="form.theatreOperaNum"
+            @focus="focusNum('theatreOperaNum')"
+            @blur="blurNum('theatreOperaNum')"
+            @input="changeClass($event, 'theatreOperaNum')"
+            :rules="[
+              {
+                validator: val => {
+                  return !isMore;
+                },
+                message: '教师总数为' + form.teacherNum
+              }
+            ]"
+          />
+          <van-field
+            type="digit"
+            name="曲艺类"
+            label="曲艺类"
+            placeholder="请输入曲艺类"
+            v-model="form.folkMusicNum"
+            @focus="focusNum('folkMusicNum')"
+            @blur="blurNum('folkMusicNum')"
+            @input="changeClass($event, 'folkMusicNum')"
+            :rules="[
+              {
+                validator: val => {
+                  return !isMore;
+                },
+                message: '教师总数为' + form.teacherNum
+              }
+            ]"
+          />
+        </div>
+
+        <van-field
+          type="digit"
+          name="有教师资格证"
+          label="有教师资格证"
+          placeholder="请输入有教师资格证"
+          v-model="form.qualificationNum"
+          :rules="[{ required: true, message: '请填写有教师资格证' }]"
+        />
+        <van-field
+          type="digit"
+          name="年培训人数"
+          label="年培训人数"
+          placeholder="请输入年培训人数"
+          v-model="form.traineesPerYearNum"
+          :rules="[{ required: true, message: '请填写年培训人数' }]"
+        />
+        <van-field
+          name="是否是艺术水平考级考点"
+          label="是否是艺术水平考级考点"
+          placeholder="请输入是否是艺术水平考级考点"
+        >
+          <template #input>
+            <van-radio-group v-model="form.examPoint" direction="horizontal">
+              <van-radio :name="true"> 是</van-radio>
+              <van-radio :name="false">否</van-radio>
+            </van-radio-group>
+          </template>
+        </van-field>
+        <van-field
+          name="艺术水平考级机构名称"
+          label="艺术水平考级机构名称"
+          placeholder="请输入艺术水平考级机构名称"
+          v-model="form.gradingOrganization"
+        />
+        <van-field
+          type="textarea"
+          name="备注"
+          label="备注"
+          placeholder="请输入备注"
+          v-model="form.remark"
+        />
+
+        <div class="bottom">
+          <van-button
+            @click="saveWeb"
+            class="preview"
+            color="#ffcf6a"
+            block
+            round
+            native-type="button"
+            style="margin-right:12px"
+            >暂存</van-button
+          >
+          <van-button
+            class="submit"
+            round
+            block
+            type="info"
+            native-type="submit"
+            >提交</van-button
+          >
+        </div>
+      </template>
+    </van-form>
+
+    <van-divider> 技术客服:19951988293</van-divider>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      form: {
+        examPoint: false
+      },
+      list: [],
+      showPopover: false,
+      activeNames: "1",
+      isMore: false,
+      showType: false,
+      types: [
+        { name: "企业" },
+        { name: "社会组织" },
+        { name: "事业单位" },
+        { name: "其他" }
+      ],
+      extra: "",
+      specialtyOptions: ["音乐类", "舞蹈类", "美术类", "戏曲戏剧类", "曲艺类"]
+    };
+  },
+  mounted() {
+    let data = JSON.parse(
+      window.localStorage.getItem("trainingInstitution") || "{}"
+    );
+    data.specialty = this.setSpecialty(data.specialty);
+    this.form = data;
+  },
+  computed: {
+    showExtra() {
+      let special = [...this.form.specialty];
+      return special.includes("其他");
+    }
+  },
+  methods: {
+    onSelect(val) {
+      this.form.category = val.name;
+    },
+    like(info, key = "") {
+      this.$toast.loading({
+        message: "加载中...",
+        forbidClick: true,
+        duration: 0
+      });
+      this.showPopover = false;
+      let data = { search: this.form.name, size: 4, query: {} };
+      if (key) {
+        data.query[key] = this.form[key];
+      }
+      this.$http
+        .post("/trainingInstitution/name", data, { body: "json" })
+        .then(res => {
+          this.$toast.clear();
+          this.list = res.content;
+          setTimeout(() => {
+            this.$nextTick(() => {
+              this.showPopover = true;
+            });
+          }, 500);
+        });
+    },
+    setSpecialty(specialty) {
+      if (specialty) {
+        specialty = specialty.split(",");
+        specialty.forEach((item, index) => {
+          if (!this.specialtyOptions.includes(item)) {
+            specialty[index] = "其他";
+            this.extra = item;
+          }
+        });
+        return specialty;
+      } else {
+        return [];
+      }
+    },
+    byUscc() {
+      this.$refs.form.validate().then(() => {
+        this.$toast.loading({
+          message: "加载中...",
+          forbidClick: true,
+          duration: 0
+        });
+        this.extra = "";
+        this.$http
+          .post(
+            `/trainingInstitution/byUscc?name=${this.form.name}&uscc=${this.form.uscc}`
+          )
+          .then(res => {
+            res.category = res.category || "";
+            res.specialty = this.setSpecialty(res.specialty);
+            this.$toast.clear();
+            this.form = { ...res, ...this.form };
+            if (!this.form.engagedInTraining) {
+              this.submit();
+            }
+          })
+          .catch(e => {
+            this.$toast(e.error);
+          });
+      });
+    },
+    choose(info) {
+      this.form.name = info;
+      // this.form = { examPoint: false, ...info };
+      this.showPopover = false;
+    },
+    submit() {
+      if (!this.form.id) {
+        return;
+      }
+      this.$toast.loading({
+        message: "加载中...",
+        forbidClick: true,
+        duration: 0
+      });
+      let data = { ...this.form };
+      data.specialty.forEach((item, index) => {
+        if (!this.specialtyOptions.includes(item)) {
+          data.specialty[index] = this.extra;
+        }
+      });
+      data.specialty = data.specialty.filter(item => {
+        return item;
+      });
+      data.specialty = data.specialty.join(",");
+      this.$http
+        .post("/trainingInstitution/save", data, { body: "json" })
+        .then(res => {
+          this.$toast.clear();
+          window.localStorage.removeItem("trainingInstitution");
+          this.$dialog({
+            title: "提交成功",
+            message: "信息已经提交成功,感谢您的配合。",
+            showConfirmButton: false
+          });
+        })
+        .catch(e => {
+          this.$toast(e.error);
+        });
+    },
+    saveWeb() {
+      let form = { ...this.form };
+      form.specialty.forEach((item, index) => {
+        if (!this.specialtyOptions.includes(item)) {
+          form.specialty[index] = this.extra;
+        }
+      });
+      form.specialty = form.specialty.filter(item => {
+        return item;
+      });
+      form.specialty = form.specialty.join(",");
+      let data = JSON.stringify(form);
+      window.localStorage.setItem("trainingInstitution", data);
+      this.$toast.success("暂存成功");
+    },
+    changeNum() {
+      this.$nextTick(() => {
+        this.form.teacherNum =
+          Number(this.form.partTimeNum) + Number(this.form.fullTimeNum);
+      });
+    },
+    changeClass(val, label) {
+      let keys = {
+        musicNum: "音乐类",
+        danceNum: "舞蹈类",
+        artNum: "美术类",
+        theatreOperaNum: "戏剧戏曲",
+        folkMusicNum: "曲艺类"
+      };
+      let total = Number(val);
+      Object.keys(keys).forEach(item => {
+        if (label !== item) {
+          total += Number(this.form[item]);
+        }
+      });
+      if (total > this.form.teacherNum) {
+        this.isMore = true;
+        this.$refs.form.validate(keys[label]);
+      } else {
+        this.isMore = false;
+      }
+    },
+    focusNum(key) {
+      if (!Number(this.form[key])) {
+        this.form[key] = "";
+      }
+    },
+    blurNum(key) {
+      this.form[key] = Number(this.form[key]);
+    },
+    changeExtra(val) {
+      console.log(val);
+      if (val) {
+        this.$refs.extra.focus();
+      }
+    }
+  }
+};
+</script>
+
+<style lang="less" scoped>
+.page {
+  position: relative;
+  padding-bottom: 100px;
+}
+/deep/.van-field {
+  margin: 16px 16px 0;
+  width: calc(100vw - 32px);
+  border-radius: 12px;
+  flex-direction: column;
+
+  .van-field__label {
+    font-size: 18px;
+    font-weight: bold;
+    color: #313233;
+    line-height: 28px;
+    width: auto;
+  }
+  .van-field__value {
+    margin-top: 14px;
+    font-size: 16px;
+    line-height: 32px;
+  }
+}
+
+.bottom {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 6px 26px calc(env(safe-area-inset-bottom) + 6px);
+  background-color: #fff;
+  z-index: 20;
+
+  display: flex;
+
+  .preview {
+    min-width: 82px;
+    width: 82px;
+  }
+  .submit {
+    flex-grow: 1;
+    // margin-left: 13px;
+  }
+}
+.panel {
+  padding: 30px 0;
+}
+.panel + .panel {
+  padding-top: 0;
+}
+
+.van-checkbox {
+  margin-bottom: 5px;
+}
+.extra-content {
+  display: flex;
+  align-items: center;
+}
+.van-divider {
+  font-size: 16px;
+}
+
+/deep/.input {
+  margin: 0;
+  width: calc(100vw - 240px);
+  border: 1px solid #ccc;
+  padding: 0px 12px;
+  border-radius: 0;
+  .van-field__value {
+    margin-top: 0;
+    line-height: 24px;
+    font-size: 14px;
+  }
+}
+
+.tips {
+}
+</style>

+ 49 - 42
src/main/h5/src/views/loginHome.vue

@@ -74,10 +74,45 @@ export default {
         message: "加载中...",
         message: "加载中...",
         forbidClick: true
         forbidClick: true
       });
       });
+      // this.$http
+      //   .post("/programme/getAuth", {
+      //     phone: this.ruleForm.phone,
+      //     id: this.$route.query.programmeId
+      //   })
+      //   .then(res => {
+      //     window.localStorage.setItem("loginPhone", res.phone);
+      //     if (res.token) {
+      //       window.localStorage.setItem("loginPhoneToken", res.token);
+      //       localStorage.setItem("token", res.token);
+      //       return this.$store.dispatch("getUserInfo");
+      //     } else {
+      //       return Promise.resolve();
+      //     }
+      //   })
+      //   .then(() => {
+      //     this.$toast.clear();
+      //     this.$router.replace({ path: "/home", query: this.$route.query });
+      //   })
+      //   .catch(e => {
+      //     if (e) {
+      //       this.$toast(e.error);
+      //       this.isSend = false;
+      //       this.ruleForm = {
+      //         phone: "",
+      //         code: ""
+      //       };
+      //     }
+      //   });
       this.$http
       this.$http
-        .post("/programme/getAuth", {
+        .get("/sms/verify", {
           phone: this.ruleForm.phone,
           phone: this.ruleForm.phone,
-          id: this.$route.query.programmeId
+          code: this.ruleForm.code
+        })
+        .then(() => {
+          return this.$http.post("/programme/getAuth", {
+            phone: this.ruleForm.phone,
+            id: this.$route.query.programmeId
+          });
         })
         })
         .then(res => {
         .then(res => {
           window.localStorage.setItem("loginPhone", res.phone);
           window.localStorage.setItem("loginPhone", res.phone);
@@ -104,34 +139,6 @@ export default {
           }
           }
         });
         });
       // this.$http
       // this.$http
-      //   .get("/sms/verify", {
-      //     phone: this.ruleForm.phone,
-      //     code: this.ruleForm.code
-      //   })
-      //   .then(() => {
-      //     return this.$http.post("/performanceApply/getAuth", {
-      //       phone: this.ruleForm.phone,
-      //       id: this.$route.query.performanceApplyId
-      //     });
-      //   })
-      //   .catch(e => {
-      //     this.$toast(e.error || "登录失败");
-      //     return Promise.reject();
-      //   })
-      //   .then(res => {
-      //     localStorage.setItem("token", res);
-      //     return this.$store.dispatch("getUserInfo");
-      //   })
-      //   .then(() => {
-      //     this.$toast.clear();
-      //     this.$router.replace({ path: "/" });
-      //   })
-      //   .catch(e => {
-      //     if (e) {
-      //       this.$toast(e.error);
-      //     }
-      //   });
-      // this.$http
       //   .post("/auth/phoneLogin", {
       //   .post("/auth/phoneLogin", {
       //     phone: this.ruleForm.phone
       //     phone: this.ruleForm.phone
       //   })
       //   })
@@ -154,18 +161,18 @@ export default {
         return;
         return;
       }
       }
 
 
-      // this.$http
-      //   .get("/sms/sendVerify", {
-      //     phone: this.ruleForm.phone
-      //   })
-      //   .then(res => {
-      //     this.$toast.success("发送成功");
-      this.isSend = true;
-      this.changeTime(60);
-      // })
-      // .catch(e => {
-      //   this.$toast(e.error);
-      // });
+      this.$http
+        .get("/sms/sendVerify", {
+          phone: this.ruleForm.phone
+        })
+        .then(res => {
+          this.$toast.success("发送成功");
+          this.isSend = true;
+          this.changeTime(60);
+        })
+        .catch(e => {
+          this.$toast(e.error);
+        });
     },
     },
     changeTime(num) {
     changeTime(num) {
       this.num = num;
       this.num = num;

+ 30 - 0
src/main/java/com/izouma/wenlvju/domain/Announcement.java

@@ -0,0 +1,30 @@
+package com.izouma.wenlvju.domain;
+
+import com.izouma.wenlvju.enums.AnnouncementType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Entity
+@Builder
+@Where(clause = "del = 0")
+public class Announcement extends BaseEntity {
+    private String title;
+
+    @Enumerated(EnumType.STRING)
+    private AnnouncementType type;
+
+    @Column(columnDefinition = "TEXT")
+    private String content;
+}

+ 2 - 0
src/main/java/com/izouma/wenlvju/domain/Rate.java

@@ -162,6 +162,8 @@ public class Rate extends BaseEntity {
     @ApiModelProperty(value = "变更地址")
     @ApiModelProperty(value = "变更地址")
     private String changeAddress;
     private String changeAddress;
 
 
+    private String pdfUrl;
+
     public String getDetailAddress() {
     public String getDetailAddress() {
         String str = "江苏省南京市" + this.district;
         String str = "江苏省南京市" + this.district;
 
 

+ 152 - 0
src/main/java/com/izouma/wenlvju/domain/TrainingInstitution.java

@@ -0,0 +1,152 @@
+package com.izouma.wenlvju.domain;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.wenlvju.annotations.Searchable;
+import com.izouma.wenlvju.utils.excel.BooleanConverter;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Entity
+@ApiModel("培训机构")
+public class TrainingInstitution extends BaseEntity {
+    @Searchable
+    @ExcelProperty(value = "企业名称")
+    @ApiModelProperty("企业名称")
+    private String name;
+
+    @ExcelProperty(value = "注册号")
+    @ApiModelProperty("注册号")
+    private String uscc;
+
+    @ApiModelProperty(value = "是否从事文化艺术类校外培训")
+    @ExcelProperty(value = "是否从事文化艺术类校外培训", converter = BooleanConverter.class)
+    private boolean engagedInTraining;
+
+    @ExcelProperty(value = "经营范围")
+    @Column(columnDefinition = "TEXT")
+    @ApiModelProperty("经营范围")
+    private String businessScope;
+
+    @ExcelProperty(value = "企业住所")
+    @ApiModelProperty("企业住所")
+    private String address;
+
+    @ExcelProperty(value = "生产经营场所")
+    @ApiModelProperty("生产经营场所")
+    private String businessPremise;
+
+    @ExcelProperty(value = "法人姓名")
+    @ApiModelProperty(value = "法人姓名")
+    private String privacyPolicy;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "短信发送号码")
+    private String phone;
+
+    @ExcelProperty(value = "企业联系方式")
+    @ApiModelProperty(value = "企业联系方式")
+    private String contactPhone;
+
+    @ExcelProperty(value = "所属管区")
+    @ApiModelProperty(value = "所属管区")
+    private String district;
+
+    @ExcelProperty(value = "注册资本(万)")
+    @ApiModelProperty(value = "注册资本(万)")
+    private BigDecimal registeredCapital;
+
+    @ExcelProperty(value = "单位性质")
+    @ApiModelProperty(value = "单位性质")
+    private String category;
+
+    @ExcelProperty(value = "专业种类")
+    @ApiModelProperty(value = "专业种类")
+    private String specialty;
+
+    @ExcelProperty(value = "培训点数量三楼及以下")
+    @ApiModelProperty(value = "培训点数量三楼及以下")
+    private int trainingSite;
+
+    @ExcelProperty(value = "培训点数量四楼及以上")
+    @ApiModelProperty(value = "培训点数量四楼及以上")
+    private int trainingSiteFour;
+
+    @ExcelProperty(value = "总面积")
+    @ApiModelProperty(value = "总面积")
+    private double area;
+
+    @ExcelProperty(value = "教室数量")
+    @ApiModelProperty(value = "教室数量")
+    private int classroomNum;
+
+    @ExcelProperty(value = "教师总数")
+    @ApiModelProperty(value = "教师总数")
+    private int teacherNum;
+
+    @ExcelProperty(value = "专职数量")
+    @ApiModelProperty(value = "专职数量")
+    private int fullTimeNum;
+
+    @ExcelProperty(value = "兼职数量")
+    @ApiModelProperty(value = "兼职数量")
+    private int partTimeNum;
+
+    @ExcelProperty(value = "音乐类")
+    @ApiModelProperty(value = "音乐类")
+    private int musicNum;
+
+    @ExcelProperty(value = "舞蹈类")
+    @ApiModelProperty(value = "舞蹈类")
+    private int danceNum;
+
+    @ExcelProperty(value = "美术类")
+    @ApiModelProperty(value = "美术类")
+    private int artNum;
+
+    @ExcelProperty(value = "戏剧戏曲类")
+    @ApiModelProperty(value = "戏剧戏曲类")
+    private int theatreOperaNum;
+
+    @ExcelProperty(value = "曲艺类")
+    @ApiModelProperty(value = "曲艺类")
+    private int folkMusicNum;
+
+    @ExcelProperty(value = "有教师资格证")
+    @ApiModelProperty(value = "有教师资格证")
+    private int qualificationNum;
+
+    @ExcelProperty(value = "年培训人数")
+    @ApiModelProperty(value = "年培训人数")
+    private long traineesPerYearNum;
+
+    @ExcelProperty(value = "是否是艺术水平考级考点", converter = BooleanConverter.class)
+    @ApiModelProperty(value = "是否是艺术水平考级考点")
+    private boolean examPoint;
+
+    @ExcelProperty(value = "艺术水平考级机构名称")
+    @ApiModelProperty(value = "艺术水平考级机构名称")
+    private String gradingOrganization;
+
+    @ExcelProperty(value = "备注")
+    @Column(columnDefinition = "TEXT")
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    private boolean submit;
+
+    private LocalDateTime firstWrite;
+}

+ 2 - 0
src/main/java/com/izouma/wenlvju/domain/performance/Participant.java

@@ -21,6 +21,8 @@ import java.time.LocalDate;
 @ApiModel(value = "参演人员")
 @ApiModel(value = "参演人员")
 @Where(clause = "del = 0")
 @Where(clause = "del = 0")
 public class Participant extends BaseEntity {
 public class Participant extends BaseEntity {
+    private Long performanceId;
+
     private Long programmeId;
     private Long programmeId;
 
 
     @ApiModelProperty(value = "姓名")
     @ApiModelProperty(value = "姓名")

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

@@ -72,6 +72,8 @@ public class Performance extends BaseEntity {
     @ApiModelProperty(value = "复审比例")
     @ApiModelProperty(value = "复审比例")
     private BigDecimal reviewRatio;
     private BigDecimal reviewRatio;
 
 
+    private boolean close;
+
     @Transient
     @Transient
     private long programmeNum;
     private long programmeNum;
 }
 }

+ 25 - 18
src/main/java/com/izouma/wenlvju/dto/ProgrammeShowDTO.java

@@ -4,72 +4,79 @@ import cn.hutool.core.bean.BeanUtil;
 import com.alibaba.excel.annotation.ExcelIgnore;
 import com.alibaba.excel.annotation.ExcelIgnore;
 import com.alibaba.excel.annotation.ExcelProperty;
 import com.alibaba.excel.annotation.ExcelProperty;
 import com.izouma.wenlvju.annotations.EnumFormat;
 import com.izouma.wenlvju.annotations.EnumFormat;
-import com.izouma.wenlvju.domain.performance.Participant;
 import com.izouma.wenlvju.domain.performance.Programme;
 import com.izouma.wenlvju.domain.performance.Programme;
 import com.izouma.wenlvju.enums.CompetitionGroup;
 import com.izouma.wenlvju.enums.CompetitionGroup;
+import com.izouma.wenlvju.enums.ProgrammeStatus;
 import com.izouma.wenlvju.utils.excel.EnumExcelConverter;
 import com.izouma.wenlvju.utils.excel.EnumExcelConverter;
-import com.izouma.wenlvju.utils.excel.LocalDateConverter;
-import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
-import lombok.Builder;
 import lombok.Data;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.NoArgsConstructor;
 
 
 import javax.persistence.EnumType;
 import javax.persistence.EnumType;
 import javax.persistence.Enumerated;
 import javax.persistence.Enumerated;
-import java.time.LocalDate;
 import java.util.List;
 import java.util.List;
 
 
 @Data
 @Data
 @AllArgsConstructor
 @AllArgsConstructor
 @NoArgsConstructor
 @NoArgsConstructor
 public class ProgrammeShowDTO {
 public class ProgrammeShowDTO {
+    @ExcelProperty(value = "节目编号")
     private Long id;
     private Long id;
 
 
-    @ApiModelProperty(value = "活动名称")
+    @ExcelIgnore
     private String performance;
     private String performance;
 
 
-    @ApiModelProperty(value = "节目名称")
+    @ExcelProperty(value = "节目名称")
     private String name;
     private String name;
 
 
-    @ApiModelProperty(value = "参赛专业")
+    @ExcelProperty(value = "参赛专业")
     private String specialty;
     private String specialty;
 
 
-    @ApiModelProperty(value = "参赛组别")
+    @EnumFormat(value = CompetitionGroup.class,
+            fromExcel = {"个人", "集体"},
+            toJavaEnum = {"SINGLE", "COLLECTIVE"})
+    @ExcelProperty(value = "参赛组别", converter = EnumExcelConverter.class)
+    @Enumerated(EnumType.STRING)
     private CompetitionGroup competitionGroup;
     private CompetitionGroup competitionGroup;
 
 
-    @ApiModelProperty(value = "参赛级别")
+    @ExcelProperty(value = "参赛级别")
     private String level;
     private String level;
 
 
-    @ApiModelProperty(value = "作品时长")
+    @ExcelProperty(value = "作品时长")
     private int durationOfWork;
     private int durationOfWork;
 
 
-    @ApiModelProperty(value = "指导老师")
+    @ExcelProperty(value = "指导老师")
     private String instructor;
     private String instructor;
 
 
-    @ApiModelProperty(value = "考级机构")
+    @ExcelProperty(value = "考级机构")
     private String gradingOrganization;
     private String gradingOrganization;
 
 
-    @ApiModelProperty(value = "承办单位")
+    @ExcelProperty(value = "承办单位")
     private String organization;
     private String organization;
 
 
-    @ApiModelProperty(value = "考级点")
+    @ExcelProperty(value = "考级点")
     private String examPoint;
     private String examPoint;
 
 
-    @ApiModelProperty(value = "联系人")
+    @ExcelProperty(value = "联系人")
     private String contact;
     private String contact;
 
 
-    @ApiModelProperty(value = "参赛人数")
+    @ExcelProperty(value = "参赛人数")
     private int quantity;
     private int quantity;
 
 
-    @ApiModelProperty(value = "评分")
+    @ExcelProperty(value = "评分")
     private Double score;
     private Double score;
 
 
+    @ExcelIgnore
     private String video;
     private String video;
 
 
+    @ExcelIgnore
     private String annex;
     private String annex;
 
 
+    @ExcelIgnore
+    private ProgrammeStatus programmeStatus;
+
+    @ExcelIgnore
     private List<ParticipantDTO> participants;
     private List<ParticipantDTO> participants;
 
 
     public ProgrammeShowDTO(Programme programme) {
     public ProgrammeShowDTO(Programme programme) {

+ 2 - 0
src/main/java/com/izouma/wenlvju/dto/RateDTO.java

@@ -88,6 +88,8 @@ public class RateDTO {
     @ApiModelProperty(value = "等级")
     @ApiModelProperty(value = "等级")
     private String grade;
     private String grade;
 
 
+    private int sort;
+
     @ExcelIgnore
     @ExcelIgnore
     @ApiModelProperty(value = "驳回时间")
     @ApiModelProperty(value = "驳回时间")
     private LocalDateTime rejectedAt;
     private LocalDateTime rejectedAt;

+ 45 - 0
src/main/java/com/izouma/wenlvju/dto/TrainingInstitutionDTO.java

@@ -0,0 +1,45 @@
+package com.izouma.wenlvju.dto;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.wenlvju.domain.TrainingInstitution;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@ApiModel("培训机构")
+public class TrainingInstitutionDTO {
+    @ExcelProperty(value = "编号")
+    private Long id;
+
+    @ExcelProperty(value = "企业名称")
+    @ApiModelProperty("企业名称")
+    private String name;
+
+    @ExcelProperty(value = "注册号")
+    @ApiModelProperty("注册号")
+    private String uscc;
+
+    @ExcelProperty(value = "法人姓名")
+    @ApiModelProperty(value = "法人姓名")
+    private String privacyPolicy;
+
+    @ExcelProperty(value = "固定电话")
+    @ApiModelProperty(value = "固定电话")
+    private String contactPhone;
+
+    @ExcelProperty(value = "移动电话")
+    @ApiModelProperty(value = "移动电话")
+    private String phone;
+
+    public TrainingInstitutionDTO(TrainingInstitution trainingInstitution) {
+        BeanUtil.copyProperties(trainingInstitution, this);
+    }
+}

+ 12 - 0
src/main/java/com/izouma/wenlvju/enums/AnnouncementType.java

@@ -0,0 +1,12 @@
+package com.izouma.wenlvju.enums;
+
+public enum AnnouncementType {
+    /**
+     * 通知
+     */
+    NOTIFICATION,
+    /**
+     * 政策
+     */
+    POLICY
+}

+ 26 - 0
src/main/java/com/izouma/wenlvju/enums/GradingOrganizationDTO.java

@@ -0,0 +1,26 @@
+package com.izouma.wenlvju.enums;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.izouma.wenlvju.domain.BaseEntity;
+import com.izouma.wenlvju.domain.GradingOrganization;
+import io.swagger.annotations.ApiModel;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@ApiModel(value = "考级机构")
+public class GradingOrganizationDTO extends BaseEntity {
+    @ExcelProperty(value = "编号")
+    private Long id;
+
+    @ExcelProperty(value = "名称")
+    private String name;
+
+    public GradingOrganizationDTO(GradingOrganization gradingOrganization) {
+        BeanUtil.copyProperties(gradingOrganization, this);
+    }
+}

+ 16 - 0
src/main/java/com/izouma/wenlvju/repo/AnnouncementRepo.java

@@ -0,0 +1,16 @@
+package com.izouma.wenlvju.repo;
+
+import com.izouma.wenlvju.domain.Announcement;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+
+public interface AnnouncementRepo extends JpaRepository<Announcement, Long>, JpaSpecificationExecutor<Announcement> {
+    @Query("update Announcement t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+}

+ 3 - 0
src/main/java/com/izouma/wenlvju/repo/RateRepo.java

@@ -30,4 +30,7 @@ public interface RateRepo extends JpaRepository<Rate, Long>, JpaSpecificationExe
 
 
     @Query(nativeQuery = true, value = "select count(1) from rate where del=0 and (expert_user_id = ?1 or find_in_set(?1,expert_member_user_id))")
     @Query(nativeQuery = true, value = "select count(1) from rate where del=0 and (expert_user_id = ?1 or find_in_set(?1,expert_member_user_id))")
     Long countByExpertId(Long userId);
     Long countByExpertId(Long userId);
+
+    List<Rate> findAllByStatusAndYearOrderByScoreDesc(RateStatus status, String year);
+
 }
 }

+ 30 - 0
src/main/java/com/izouma/wenlvju/repo/TrainingInstitutionRepo.java

@@ -0,0 +1,30 @@
+package com.izouma.wenlvju.repo;
+
+import com.izouma.wenlvju.domain.TrainingInstitution;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+import java.util.List;
+
+public interface TrainingInstitutionRepo extends JpaRepository<TrainingInstitution, Long>, JpaSpecificationExecutor<TrainingInstitution> {
+    @Query("update TrainingInstitution t set t.del = true where t.id = ?1")
+    @Modifying
+    @Transactional
+    void softDelete(Long id);
+
+    @Query(nativeQuery = true, value = "select DISTINCT phone from training_institution where submit = false and phone REGEXP '^[1][356789][0-9]{9}$'")
+    List<String> findAllBySubmitFalseAndPhoneIsNotNull();
+
+    @Query(nativeQuery = true, value = "select DISTINCT phone from training_institution where submit = false and phone REGEXP '^[1][356789][0-9]{9}$' limit 2000,2000")
+    List<String> findAllBySubmitFalseAndPhoneIsNotNullLimit();
+
+    List<TrainingInstitution> findAllByPhoneIsNull();
+
+    @Query(nativeQuery = true, value = "select name from training_institution where name like ?1 limit ?2,?3")
+    List<String> findAllByNameLike(String name, int page, int size);
+
+    TrainingInstitution findByUscc(String uscc);
+}

+ 7 - 0
src/main/java/com/izouma/wenlvju/repo/performance/ParticipantRepo.java

@@ -16,7 +16,14 @@ public interface ParticipantRepo extends JpaRepository<Participant, Long>, JpaSp
     @Transactional
     @Transactional
     void softDelete(Long id);
     void softDelete(Long id);
 
 
+    @Query("update Participant t set t.del = true where t.programmeId = ?1")
+    @Modifying
+    @Transactional
+    void softDeleteProgrammeId(Long programmeId);
+
     List<Participant> findAllByProgrammeIdIn(Collection<Long> ids);
     List<Participant> findAllByProgrammeIdIn(Collection<Long> ids);
 
 
     List<Participant> findAllByProgrammeId(Long id);
     List<Participant> findAllByProgrammeId(Long id);
+
+    List<Participant> findByIdNoAndPerformanceId(String idNo, Long performanceId);
 }
 }

+ 4 - 0
src/main/java/com/izouma/wenlvju/security/WebSecurityConfig.java

@@ -71,8 +71,11 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/district/NJ").permitAll()
                 .antMatchers("/district/NJ").permitAll()
                 .antMatchers("/setting/byFlag").permitAll()
                 .antMatchers("/setting/byFlag").permitAll()
                 .antMatchers("/programme/getShow/**").permitAll()
                 .antMatchers("/programme/getShow/**").permitAll()
+                .antMatchers("/programme/excelGO").permitAll()
+                .antMatchers("/programme/showAll").permitAll()
                 .antMatchers("/programme/getAuth").permitAll()
                 .antMatchers("/programme/getAuth").permitAll()
                 .antMatchers("/programme/getScore/**").permitAll()
                 .antMatchers("/programme/getScore/**").permitAll()
+                .antMatchers("/organization/byName").permitAll()
                 .antMatchers("/programmeScore/breakdown").permitAll()
                 .antMatchers("/programmeScore/breakdown").permitAll()
                 .antMatchers("/participant/byProgramme").permitAll()
                 .antMatchers("/participant/byProgramme").permitAll()
                 .antMatchers("/upload/**").permitAll()
                 .antMatchers("/upload/**").permitAll()
@@ -81,6 +84,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/auth/**").permitAll()
                 .antMatchers("/auth/**").permitAll()
                 .antMatchers("/captcha/**").permitAll()
                 .antMatchers("/captcha/**").permitAll()
                 .antMatchers("/admin/**").permitAll()
                 .antMatchers("/admin/**").permitAll()
+                .antMatchers("/trainingInstitution/**").permitAll()
                 .antMatchers("/systemVariable/all").permitAll()
                 .antMatchers("/systemVariable/all").permitAll()
                 .antMatchers("/**/excel").permitAll()
                 .antMatchers("/**/excel").permitAll()
                 .antMatchers("/wx/**").permitAll()
                 .antMatchers("/wx/**").permitAll()

+ 20 - 0
src/main/java/com/izouma/wenlvju/service/AnnouncementService.java

@@ -0,0 +1,20 @@
+package com.izouma.wenlvju.service;
+
+import com.izouma.wenlvju.domain.Announcement;
+import com.izouma.wenlvju.dto.PageQuery;
+import com.izouma.wenlvju.repo.AnnouncementRepo;
+import com.izouma.wenlvju.utils.JpaUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.stereotype.Service;
+
+@Service
+@AllArgsConstructor
+public class AnnouncementService {
+
+    private AnnouncementRepo announcementRepo;
+
+    public Page<Announcement> all(PageQuery pageQuery) {
+        return announcementRepo.findAll(JpaUtils.toSpecification(pageQuery, Announcement.class), JpaUtils.toPageRequest(pageQuery));
+    }
+}

+ 19 - 25
src/main/java/com/izouma/wenlvju/service/RateExpertAuditService.java

@@ -2,16 +2,12 @@ package com.izouma.wenlvju.service;
 
 
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.izouma.wenlvju.domain.Rate;
 import com.izouma.wenlvju.domain.Rate;
-import com.izouma.wenlvju.domain.RateAudit;
 import com.izouma.wenlvju.domain.RateExpertAudit;
 import com.izouma.wenlvju.domain.RateExpertAudit;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.dto.PageQuery;
-import com.izouma.wenlvju.enums.OrganizationGrade;
 import com.izouma.wenlvju.enums.RateStatus;
 import com.izouma.wenlvju.enums.RateStatus;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.exception.BusinessException;
-import com.izouma.wenlvju.repo.RateAuditRepo;
 import com.izouma.wenlvju.repo.RateExpertAuditRepo;
 import com.izouma.wenlvju.repo.RateExpertAuditRepo;
 import com.izouma.wenlvju.repo.RateRepo;
 import com.izouma.wenlvju.repo.RateRepo;
-import com.izouma.wenlvju.service.sms.NjwlSmsService;
 import com.izouma.wenlvju.utils.JpaUtils;
 import com.izouma.wenlvju.utils.JpaUtils;
 import com.izouma.wenlvju.utils.ObjUtils;
 import com.izouma.wenlvju.utils.ObjUtils;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
@@ -26,8 +22,6 @@ public class RateExpertAuditService {
 
 
     private final RateExpertAuditRepo rateExpertAuditRepo;
     private final RateExpertAuditRepo rateExpertAuditRepo;
     private final RateRepo            rateRepo;
     private final RateRepo            rateRepo;
-    private final NjwlSmsService      njwlSmsService;
-    private final RateAuditRepo       rateAuditRepo;
 
 
     public Page<RateExpertAudit> all(PageQuery pageQuery) {
     public Page<RateExpertAudit> all(PageQuery pageQuery) {
         return rateExpertAuditRepo.findAll(JpaUtils.toSpecification(pageQuery, RateExpertAudit.class), JpaUtils.toPageRequest(pageQuery));
         return rateExpertAuditRepo.findAll(JpaUtils.toSpecification(pageQuery, RateExpertAudit.class), JpaUtils.toPageRequest(pageQuery));
@@ -53,30 +47,30 @@ public class RateExpertAuditService {
         });
         });
     }
     }
 
 
-    public void grade(Long rateId, Long userId) {
+    public void grade(Long rateId) {
         List<RateExpertAudit> audits = rateExpertAuditRepo.findAllByRateId(rateId);
         List<RateExpertAudit> audits = rateExpertAuditRepo.findAllByRateId(rateId);
         int sum = audits.stream().mapToInt(RateExpertAudit::getExpertScore).sum();
         int sum = audits.stream().mapToInt(RateExpertAudit::getExpertScore).sum();
-        OrganizationGrade grade;
-        if (sum >= 40) {
-            grade = OrganizationGrade.EXCELLENT;
-        } else if (sum >= 20) {
-            grade = OrganizationGrade.ELIGIBLE;
-        } else {
-            grade = OrganizationGrade.NOT_ELIGIBLE;
-        }
+//        OrganizationGrade grade;
+//        if (sum >= 40) {
+//            grade = OrganizationGrade.EXCELLENT;
+//        } else if (sum >= 20) {
+//            grade = OrganizationGrade.ELIGIBLE;
+//        } else {
+//            grade = OrganizationGrade.NOT_ELIGIBLE;
+//        }
         Rate rate = rateRepo.findById(rateId).orElseThrow(new BusinessException("无申请"));
         Rate rate = rateRepo.findById(rateId).orElseThrow(new BusinessException("无申请"));
         rate.setScore(sum + 40);
         rate.setScore(sum + 40);
-        rate.setGrade(grade);
-        rate.setStatus(RateStatus.SUBMIT_PAPER_MATERIALS);
+//        rate.setGrade(grade);
+        rate.setStatus(RateStatus.SUBMIT_GRADE);
         rateRepo.save(rate);
         rateRepo.save(rate);
-        RateAudit rateAudit = RateAudit.builder()
-                .userId(userId)
-                .rateId(rateId)
-                .remark("市政管理员已评审完成,请你单位在5个工作日内将纸质申请材料(2份)送属地区文化行政主管部门。")
-                .status(RateStatus.SUBMIT_PAPER_MATERIALS.toString())
-                .build();
-        rateAuditRepo.save(rateAudit);
+//        RateAudit rateAudit = RateAudit.builder()
+//                .userId(userId)
+//                .rateId(rateId)
+//                .remark("市政管理员已评审完成,请你单位在5个工作日内将纸质申请材料(2份)送属地区文化行政主管部门。")
+//                .status(RateStatus.SUBMIT_PAPER_MATERIALS.toString())
+//                .build();
+//        rateAuditRepo.save(rateAudit);
         // 市区评分发送短信
         // 市区评分发送短信
-        njwlSmsService.sendSms(rate.getOwnerPhone(), "请你单位在5个工作日内将纸质申请材料(2份)送属" + rate.getDistrict() + "文化和旅游局文化行政主管部门,期不送,作自动放弃处理。");
+//        njwlSmsService.sendSms(rate.getOwnerPhone(), "请你单位在5个工作日内将纸质申请材料(2份)送属" + rate.getDistrict() + "文化和旅游局文化行政主管部门,期不送,作自动放弃处理。");
     }
     }
 }
 }

+ 211 - 22
src/main/java/com/izouma/wenlvju/service/RateService.java

@@ -9,11 +9,13 @@ import com.izouma.wenlvju.domain.*;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.dto.ReviewTime;
 import com.izouma.wenlvju.dto.ReviewTime;
 import com.izouma.wenlvju.enums.AuthorityName;
 import com.izouma.wenlvju.enums.AuthorityName;
+import com.izouma.wenlvju.enums.OrganizationGrade;
 import com.izouma.wenlvju.enums.RateStatus;
 import com.izouma.wenlvju.enums.RateStatus;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.repo.*;
 import com.izouma.wenlvju.repo.*;
 import com.izouma.wenlvju.security.Authority;
 import com.izouma.wenlvju.security.Authority;
 import com.izouma.wenlvju.service.sms.NjwlSmsService;
 import com.izouma.wenlvju.service.sms.NjwlSmsService;
+import com.izouma.wenlvju.utils.FileUtils;
 import com.izouma.wenlvju.utils.JpaUtils;
 import com.izouma.wenlvju.utils.JpaUtils;
 import com.izouma.wenlvju.utils.ObjUtils;
 import com.izouma.wenlvju.utils.ObjUtils;
 import com.lowagie.text.Document;
 import com.lowagie.text.Document;
@@ -28,6 +30,8 @@ import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.pdfbox.io.MemoryUsageSetting;
 import org.apache.pdfbox.io.MemoryUsageSetting;
 import org.apache.pdfbox.multipdf.PDFMergerUtility;
 import org.apache.pdfbox.multipdf.PDFMergerUtility;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
@@ -44,16 +48,25 @@ import java.util.stream.Collectors;
 
 
 @Service
 @Service
 @Slf4j
 @Slf4j
-@AllArgsConstructor
+//@AllArgsConstructor
 public class RateService {
 public class RateService {
 
 
-    private final RateRepo                rateRepo;
-    private final CollaborateRepo         collaborateRepo;
-    private final GradingOrganizationRepo gradingOrganizationRepo;
-    private final RateAuditRepo           rateAuditRepo;
-    private final UserRepo                userRepo;
-    private final NjwlSmsService          njwlSmsService;
-    private final OrganizationRepo        organizationRepo;
+    @Autowired
+    private RateRepo                rateRepo;
+    @Autowired
+    private CollaborateRepo         collaborateRepo;
+    @Autowired
+    private GradingOrganizationRepo gradingOrganizationRepo;
+    @Autowired
+    private RateAuditRepo           rateAuditRepo;
+    @Autowired
+    private UserRepo                userRepo;
+    @Autowired
+    private NjwlSmsService          njwlSmsService;
+    @Autowired
+    private OrganizationRepo        organizationRepo;
+    @Value("${storage.local_path}")
+    private String                  localPath;
 
 
     public Page<Rate> all(PageQuery pageQuery) {
     public Page<Rate> all(PageQuery pageQuery) {
         return rateRepo.findAll(JpaUtils.toSpecification(pageQuery, Rate.class), JpaUtils.toPageRequest(pageQuery));
         return rateRepo.findAll(JpaUtils.toSpecification(pageQuery, Rate.class), JpaUtils.toPageRequest(pageQuery));
@@ -227,11 +240,17 @@ public class RateService {
                 .status(status.toString())
                 .status(status.toString())
                 .build();
                 .build();
         rateAuditRepo.save(rateAudit);
         rateAuditRepo.save(rateAudit);
-        if (RateStatus.COMPLETE.equals(status)) {
-            njwlSmsService.sendSms(rate.getOwnerPhone(), "等级评定结果公告已发布,请在南京市文化和旅游局官方网站(http://wlj.nanjing.gov.cn/)上查询。");
-        }
+//        if (RateStatus.COMPLETE.equals(status)) {
+//            njwlSmsService.sendSms(rate.getOwnerPhone(), "等级评定结果公告已发布,请在南京市文化和旅游局官方网站(http://wlj.nanjing.gov.cn/)上查询。");
+//        }
     }
     }
 
 
+    /**
+     * 生成word模版
+     *
+     * @param rate
+     * @return
+     */
     public String export(Rate rate) {
     public String export(Rate rate) {
         Map<String, Object> dataMap = new HashMap<>();
         Map<String, Object> dataMap = new HashMap<>();
         try {
         try {
@@ -249,6 +268,7 @@ public class RateService {
             //承办过
             //承办过
             dataMap.put("undertake", rate.isUndertakeExamination() ? "是" : "否");
             dataMap.put("undertake", rate.isUndertakeExamination() ? "是" : "否");
             //考级机构名称
             //考级机构名称
+            dataMap.put("examination", "");
             Set<Long> ids = collaborateRepo.findAllByRateId(rate.getId())
             Set<Long> ids = collaborateRepo.findAllByRateId(rate.getId())
                     .stream()
                     .stream()
                     .map(Collaborate::getGradingOrganizationId)
                     .map(Collaborate::getGradingOrganizationId)
@@ -263,6 +283,9 @@ public class RateService {
 
 
             //单位概况
             //单位概况
             dataMap.put("introduction", rate.getIntroduction());
             dataMap.put("introduction", rate.getIntroduction());
+            //等级
+            dataMap.put("grade", rate.getGrade().getDesc());
+
             //Configuration 用于读取ftl文件
             //Configuration 用于读取ftl文件
             Configuration configuration = new Configuration(new Version("2.3.0"));
             Configuration configuration = new Configuration(new Version("2.3.0"));
 
 
@@ -290,7 +313,12 @@ public class RateService {
         this.addList(imageUrllist, rate.getFinance());
         this.addList(imageUrllist, rate.getFinance());
         this.addList(imageUrllist, rate.getProperty());
         this.addList(imageUrllist, rate.getProperty());
 
 
-        String filename = "img.pdf";
+        if (CollUtil.isEmpty(imageUrllist)) {
+            return;
+        }
+
+        String filename = "img" + UUID.randomUUID() + ".pdf";
+        File file = null;
 
 
         Document doc = new Document(PageSize.A4, 20, 20, 20, 20);
         Document doc = new Document(PageSize.A4, 20, 20, 20, 20);
         try {
         try {
@@ -308,10 +336,13 @@ public class RateService {
                 png1.setAlignment(Image.MIDDLE);
                 png1.setAlignment(Image.MIDDLE);
                 png1.scalePercent(percent + 3);// 表示是原来图像的比例;
                 png1.scalePercent(percent + 3);// 表示是原来图像的比例;
                 doc.add(png1);
                 doc.add(png1);
+
+
             }
             }
 //            b = os.toByteArray();
 //            b = os.toByteArray();
 
 
-            File file = new File(filename);
+            file = new File(filename);
+
             InputStream is = new FileInputStream(file);
             InputStream is = new FileInputStream(file);
             files.add(is);
             files.add(is);
 
 
@@ -319,6 +350,7 @@ public class RateService {
             e.printStackTrace();
             e.printStackTrace();
         } finally {
         } finally {
             doc.close();
             doc.close();
+            FileUtils.delFiles(file);
         }
         }
     }
     }
 
 
@@ -376,15 +408,35 @@ public class RateService {
         urls.forEach(privacy -> {
         urls.forEach(privacy -> {
             num.getAndIncrement();
             num.getAndIncrement();
             if ("doc".equals(getSuffix(privacy)) || "docx".equals(getSuffix(privacy))) {
             if ("doc".equals(getSuffix(privacy)) || "docx".equals(getSuffix(privacy))) {
-                InputStream is1 = HttpRequest.get(privacy)
-                        .stream();
+                InputStream is1;
+                if (privacy.contains("http")) {
+                    is1 = HttpRequest.get(privacy)
+                            .stream();
+                } else {
+                    try {
+                        is1 = new FileInputStream(privacy);
+                    } catch (FileNotFoundException e) {
+                        throw new BusinessException("找不到文件");
+                    }
+                }
                 InputStream stream = HttpRequest.post("http://convert.izouma.com/word2pdf")
                 InputStream stream = HttpRequest.post("http://convert.izouma.com/word2pdf")
                         .accept("*/*")
                         .accept("*/*")
                         .part("file", "审核材料.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", is1)
                         .part("file", "审核材料.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", is1)
                         .stream();
                         .stream();
                 files.add(stream);
                 files.add(stream);
             } else if ("pdf".equals(getSuffix(privacy))) {
             } else if ("pdf".equals(getSuffix(privacy))) {
-                InputStream stream = HttpRequest.get(privacy).stream();
+                InputStream stream;
+                if (privacy.contains("http")) {
+                    stream = HttpRequest.get(privacy)
+                            .stream();
+                } else {
+                    try {
+                        stream = new FileInputStream(privacy);
+                    } catch (FileNotFoundException e) {
+                        throw new BusinessException("找不到文件");
+                    }
+                }
+//                InputStream stream = HttpRequest.get(privacy).stream();
                 files.add(stream);
                 files.add(stream);
             }
             }
         });
         });
@@ -433,11 +485,17 @@ public class RateService {
         return url.substring(index + 1);
         return url.substring(index + 1);
     }
     }
 
 
-    public void exportPdf(Long id, HttpServletResponse response) throws IOException {
+    /**
+     * 合并并下载pdf
+     *
+     * @param id
+     * @param response
+     * @throws IOException
+     */
+    public void exportPdf1(Long id, HttpServletResponse response) throws IOException {
         Rate rate = rateRepo.findById(id).orElseThrow(new BusinessException("无记录"));
         Rate rate = rateRepo.findById(id).orElseThrow(new BusinessException("无记录"));
         List<InputStream> files = this.upLoad1(rate);
         List<InputStream> files = this.upLoad1(rate);
 
 
-
         // pdf合并工具类
         // pdf合并工具类
         PDFMergerUtility mergePdf = new PDFMergerUtility();
         PDFMergerUtility mergePdf = new PDFMergerUtility();
         mergePdf.addSources(files);
         mergePdf.addSources(files);
@@ -448,10 +506,6 @@ public class RateService {
 
 
         mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
         mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
 
 
-        // 设置合并生成pdf文件名称
-//        String targetPath = "/Users/qiufangchao/Desktop/result.pdf";
-//        mergePdf.setDestinationFileName(targetPath);
-
         for (InputStream is : files) {
         for (InputStream is : files) {
             is.close();
             is.close();
         }
         }
@@ -466,6 +520,76 @@ public class RateService {
         outputStream.close();
         outputStream.close();
     }
     }
 
 
+    /**
+     * 下载pdf
+     *
+     * @param id
+     * @param response
+     * @throws IOException
+     */
+    public byte[] exportPdf(Long id, HttpServletResponse response) throws IOException {
+        Rate rate = rateRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+
+        // 设置response的Header
+        response.setContentType("application/pdf");
+        response.addHeader("Content-Disposition", "attachment;filename=" + "result.pdf");
+
+        String pdfUrl = rate.getPdfUrl();
+
+        int start = pdfUrl.indexOf("/pdf");
+        String end = pdfUrl.substring(start + 1);
+        File file = new File(localPath + end);
+
+        // 以流的形式下载文件。
+        InputStream fis = new BufferedInputStream(new FileInputStream(file));
+        byte[] buffer = new byte[fis.available()];
+
+        fis.read(buffer);
+        fis.close();
+
+        //删除文件
+        FileUtils.delFiles(file);
+        return buffer;
+
+//        OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
+//        toClient.write(buffer);
+//        toClient.flush();
+//        toClient.close();
+
+    }
+
+    /**
+     * 合并pdf
+     *
+     * @param rate
+     * @throws IOException
+     */
+    public void mergePdf(Rate rate) throws IOException {
+        List<InputStream> files = this.upLoad1(rate);
+
+        String targetPath = "/Users/qiufangchao/Desktop/rate/material" + rate.getId() + ".pdf";
+        // pdf合并工具类
+        PDFMergerUtility mergePdf = new PDFMergerUtility();
+
+        mergePdf.addSources(files);
+        // 设置合并生成pdf文件名称
+        mergePdf.setDestinationFileName(targetPath);
+        try {
+            mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
+            for (InputStream is : files) {
+                is.close();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 选专家发消息
+     *
+     * @param rate
+     * @return
+     */
     public Map<String, String> reviewTimesMessage(Rate rate) {
     public Map<String, String> reviewTimesMessage(Rate rate) {
         List<Long> ids = new ArrayList<>(rate.getExpertMemberUserId());
         List<Long> ids = new ArrayList<>(rate.getExpertMemberUserId());
         ids.add(rate.getExpertUserId());
         ids.add(rate.getExpertUserId());
@@ -606,4 +730,69 @@ public class RateService {
         map.put("phone", phone);
         map.put("phone", phone);
         return map;
         return map;
     }
     }
+
+    /**
+     * 发短信
+     *
+     * @param announcement 是否公告短信
+     */
+    public void batchSendSms(boolean announcement) {
+        List<Rate> rates = rateRepo.findAllByStatusAndYearOrderByScoreDesc(RateStatus.SUBMIT_PAPER_MATERIALS, String.valueOf(LocalDate.now()
+                .getYear()));
+        String phones = rates.stream().map(Rate::getOwnerPhone).collect(Collectors.joining(","));
+
+        if (announcement) {
+            njwlSmsService.sendSms(phones, "等级评定结果公告已发布,请在南京市文化和旅游局官方网站(http://wlj.nanjing.gov.cn/)上查询。");
+        } else {
+            njwlSmsService.sendSms(phones, "【宁艺通】2021年南京考级承办单位等级评定工作已完成,拟评定结果已在南京市文化和旅游局官网公示。请你单位登陆“宁艺通”等级评定系统下载打印等级评定材料,并于11月15日前将纸质申报表及完整佐证材料(各2份)送属地区文化和旅游局履行线下审核程序,逾期不送,作自动放弃处理。");
+        }
+    }
+
+    /**
+     * 等级
+     */
+    public void gradeRatio(double excellent, double eligible, Long userId) {
+        List<Rate> rates = rateRepo.findAllByStatusAndYearOrderByScoreDesc(RateStatus.SUBMIT_GRADE, String.valueOf(LocalDate.now()
+                .getYear()));
+//        rates.sort((a, b) -> Integer.compare(b.getScore(), a.getSort()));
+        int size = rates.size();
+        int excellentSum = (int) Math.round(size * excellent / 100);
+        if (excellentSum >= size) {
+            rates.forEach(rate -> {
+                rate.setGrade(OrganizationGrade.EXCELLENT);
+                rate.setStatus(RateStatus.SUBMIT_PAPER_MATERIALS);
+                RateAudit rateAudit = RateAudit.builder()
+                        .userId(userId)
+                        .rateId(rate.getId())
+                        .remark("市政管理员已评审完成,请你单位在5个工作日内将纸质申请材料(2份)送属地区文化行政主管部门。")
+                        .status(RateStatus.SUBMIT_PAPER_MATERIALS.toString())
+                        .build();
+                rateAuditRepo.save(rateAudit);
+            });
+            rateRepo.saveAll(rates);
+            return;
+        }
+
+        int eligibleSum = (int) Math.round(size * eligible / 100);
+        int total = eligibleSum + excellentSum;
+        for (int i = 0; i < size; i++) {
+            Rate rate = rates.get(i);
+            if (i < excellentSum) {
+                rate.setGrade(OrganizationGrade.EXCELLENT);
+            } else if (i < total) {
+                rate.setGrade(OrganizationGrade.ELIGIBLE);
+            } else {
+                rate.setGrade(OrganizationGrade.NOT_ELIGIBLE);
+            }
+            rate.setStatus(RateStatus.SUBMIT_PAPER_MATERIALS);
+            RateAudit rateAudit = RateAudit.builder()
+                    .userId(userId)
+                    .rateId(rate.getId())
+                    .remark("市政管理员已评审完成,请你单位在5个工作日内将纸质申请材料(2份)送属地区文化行政主管部门。")
+                    .status(RateStatus.SUBMIT_PAPER_MATERIALS.toString())
+                    .build();
+            rateAuditRepo.save(rateAudit);
+        }
+        rateRepo.saveAll(rates);
+    }
 }
 }

+ 98 - 0
src/main/java/com/izouma/wenlvju/service/TrainingInstitutionService.java

@@ -0,0 +1,98 @@
+package com.izouma.wenlvju.service;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.excel.EasyExcel;
+import com.izouma.wenlvju.domain.TrainingInstitution;
+import com.izouma.wenlvju.dto.PageQuery;
+import com.izouma.wenlvju.dto.TrainingInstitutionDTO;
+import com.izouma.wenlvju.exception.BusinessException;
+import com.izouma.wenlvju.repo.TrainingInstitutionRepo;
+import com.izouma.wenlvju.service.sms.NjwlSmsService;
+import com.izouma.wenlvju.utils.JpaUtils;
+import com.izouma.wenlvju.utils.excel.UploadDataListener;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.transaction.Transactional;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Service
+@AllArgsConstructor
+public class TrainingInstitutionService {
+
+    private TrainingInstitutionRepo trainingInstitutionRepo;
+    private NjwlSmsService          njwlSmsService;
+
+    public Page<TrainingInstitution> all(PageQuery pageQuery) {
+        return trainingInstitutionRepo.findAll(JpaUtils.toSpecification(pageQuery, TrainingInstitution.class), JpaUtils.toPageRequest(pageQuery));
+    }
+
+    public void batchSend(List<String> phones) throws InterruptedException {
+
+        int count = phones.size() / 980;
+        String body = "尊敬的调研对象:\n" +
+                "您好,为贯彻落实国家、省、市关于“双减”工作相关文件精神,了解和掌握我市文化艺术类校外培训机构相关情况,市文旅局决定开展全市文化艺术类校外培训机构网上问卷调查,如从事文化艺术类校外培训,请登录:http://wljtest.izouma.com/h5/trainingInstitution,填写调查问卷,如不从事文化艺术类校外培训,请忽略本条信息,谢谢。\n";
+        for (int i = 0; i <= count; i++) {
+            int start = i * 980;
+            int end = start + 980;
+            if (end > phones.size()) {
+                end = phones.size();
+            }
+            List<String> result = phones.subList(start, end);
+            String sendPhone = String.join(",", result);
+//            System.out.println(sendPhone);
+            njwlSmsService.sendSms(sendPhone, body);
+//            System.out.println("start:" + start + ",end:" + end);
+            // 睡眠5分钟
+            Thread.sleep(2 * 60 * 1000);
+        }
+
+    }
+
+    @Transactional(rollbackOn = Exception.class)
+    public void upload(MultipartFile file) throws IOException, InterruptedException {
+        UploadDataListener<TrainingInstitutionDTO> listener = new UploadDataListener<>();
+        List<TrainingInstitutionDTO> dtos = EasyExcel.read(file.getInputStream(), TrainingInstitutionDTO.class, listener)
+                .sheet()
+                .doReadSync();
+        List<Long> ids = dtos.stream().map(TrainingInstitutionDTO::getId).collect(Collectors.toList());
+        List<TrainingInstitution> all = trainingInstitutionRepo.findAllById(ids);
+        Map<Long, TrainingInstitution> tiMap = all
+                .stream()
+                .collect(Collectors.toMap(TrainingInstitution::getId, trainingInstitution -> trainingInstitution));
+
+        dtos.forEach(dto -> {
+            TrainingInstitution trainingInstitution = tiMap.get(dto.getId());
+            if (ObjectUtil.isNotNull(trainingInstitution)) {
+                trainingInstitution.setPhone(dto.getPhone());
+                trainingInstitutionRepo.save(trainingInstitution);
+            }
+        });
+
+        // 发送短信
+        this.batchSend(dtos.stream().map(TrainingInstitutionDTO::getPhone).collect(Collectors.toList()));
+
+    }
+
+    public List<String> byName(PageQuery pageQuery) {
+        String name = "%" + pageQuery.getSearch() + "%";
+        PageRequest pageRequest = JpaUtils.toPageRequest(pageQuery);
+        return trainingInstitutionRepo.findAllByNameLike(name, pageRequest.getPageNumber(), pageRequest.getPageSize());
+    }
+
+    public TrainingInstitution byUscc(String name, String uscc) {
+        TrainingInstitution byUscc = trainingInstitutionRepo.findByUscc(uscc.trim());
+        if (ObjectUtil.isNotNull(byUscc)) {
+            if (byUscc.getName().equals(name.trim())) {
+                return byUscc;
+            }
+        }
+        throw new BusinessException("企业名称或税号不正确");
+    }
+}

+ 25 - 0
src/main/java/com/izouma/wenlvju/service/UserService.java

@@ -5,6 +5,7 @@ import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
 import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import com.izouma.wenlvju.config.Constants;
 import com.izouma.wenlvju.config.Constants;
 import com.izouma.wenlvju.domain.*;
 import com.izouma.wenlvju.domain.*;
 import com.izouma.wenlvju.domain.performance.Participant;
 import com.izouma.wenlvju.domain.performance.Participant;
@@ -365,4 +366,28 @@ public class UserService {
         map.put("token", token);
         map.put("token", token);
         return map;
         return map;
     }
     }
+
+    public String byPhone(String account) {
+        User user = userRepo.findByUsernameAndDelFalse(account);
+        if (ObjectUtil.isNotNull(user)) {
+            return account;
+        }
+        User byPhone = userRepo.findByPhoneAndDelFalse(account);
+        if (ObjectUtil.isNotNull(byPhone)) {
+            return byPhone.getUsername();
+        }
+        return null;
+    }
+
+    public void forgetPassword(String name, String phone, String password) {
+        User user = userRepo.findByPhoneAndDelFalse(phone);
+        if (ObjectUtil.isNull(user)) {
+            throw new BusinessException("此手机号并未注册!");
+        }
+        if (StrUtil.isEmpty(name) || !user.getWork().contains(name.trim())) {
+            throw new BusinessException("企业名称不正确");
+        }
+        user.setPassword(new BCryptPasswordEncoder().encode(password));
+        userRepo.save(user);
+    }
 }
 }

+ 23 - 0
src/main/java/com/izouma/wenlvju/service/performance/ParticipantService.java

@@ -1,5 +1,7 @@
 package com.izouma.wenlvju.service.performance;
 package com.izouma.wenlvju.service.performance;
 
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import com.izouma.wenlvju.domain.performance.Participant;
 import com.izouma.wenlvju.domain.performance.Participant;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.exception.BusinessException;
@@ -27,9 +29,30 @@ public class ParticipantService {
             if (participant.getId() != null) {
             if (participant.getId() != null) {
                 Participant orig = participantRepo.findById(participant.getId())
                 Participant orig = participantRepo.findById(participant.getId())
                         .orElseThrow(new BusinessException("无记录"));
                         .orElseThrow(new BusinessException("无记录"));
+
+                if (!participant.isDel() && StrUtil.isNotEmpty(participant.getIdNo())) {
+                    List<Participant> byIdNo = participantRepo.findByIdNoAndPerformanceId(participant.getIdNo(), participant.getPerformanceId());
+                    if (CollUtil.isNotEmpty(byIdNo)) {
+                        if (byIdNo.size() > 1) {
+                            throw new BusinessException("一人只能报一个节目");
+                        } else {
+                            if (!byIdNo.get(0).getId().equals(participant.getId())) {
+                                throw new BusinessException("一人只能报一个节目");
+                            }
+                        }
+                    }
+                }
+
                 ObjUtils.merge(orig, participant);
                 ObjUtils.merge(orig, participant);
                 participantRepo.save(orig);
                 participantRepo.save(orig);
             } else {
             } else {
+                if (StrUtil.isNotEmpty(participant.getIdNo())) {
+                    List<Participant> byIdNo = participantRepo.findByIdNoAndPerformanceId(participant.getIdNo(), participant.getPerformanceId());
+                    if (CollUtil.isNotEmpty(byIdNo)) {
+                        throw new BusinessException("一人只能报一个节目");
+                    }
+                }
+
                 participantRepo.save(participant);
                 participantRepo.save(participant);
             }
             }
         });
         });

+ 184 - 119
src/main/java/com/izouma/wenlvju/service/performance/ProgrammeService.java

@@ -40,12 +40,13 @@ import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponse;
 import javax.transaction.Transactional;
 import javax.transaction.Transactional;
 import java.io.*;
 import java.io.*;
-import java.math.BigDecimal;
+import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.*;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 @Service
 @Service
@@ -98,9 +99,9 @@ public class ProgrammeService {
             if (ProgrammeStatus.INITIAL.equals(orig.getProgrammeStatus())) {
             if (ProgrammeStatus.INITIAL.equals(orig.getProgrammeStatus())) {
                 Performance performance = performanceRepo.findById(orig.getPerformanceId())
                 Performance performance = performanceRepo.findById(orig.getPerformanceId())
                         .orElseThrow(new BusinessException("无展演活动"));
                         .orElseThrow(new BusinessException("无展演活动"));
-                if (LocalDate.now().isAfter(performance.getEndDate())) {
-                    throw new BusinessException("活动已报名结束!");
-                }
+//                if (LocalDate.now().isAfter(performance.getEndDate())) {
+//                    throw new BusinessException("活动已报名结束!");
+//                }
             }
             }
             ObjUtils.merge(orig, record);
             ObjUtils.merge(orig, record);
             orig.setParentSpecialtyId(artTypeService.getParent(orig.getSpecialtyId()));
             orig.setParentSpecialtyId(artTypeService.getParent(orig.getSpecialtyId()));
@@ -108,9 +109,9 @@ public class ProgrammeService {
         } else {
         } else {
             Performance performance = performanceRepo.findById(record.getPerformanceId())
             Performance performance = performanceRepo.findById(record.getPerformanceId())
                     .orElseThrow(new BusinessException("无展演活动"));
                     .orElseThrow(new BusinessException("无展演活动"));
-            if (LocalDate.now().isAfter(performance.getEndDate())) {
-                throw new BusinessException("活动已报名结束!");
-            }
+//            if (LocalDate.now().isAfter(performance.getEndDate())) {
+//                throw new BusinessException("活动已报名结束!");
+//            }
             record.setParentSpecialtyId(artTypeService.getParent(record.getSpecialtyId()));
             record.setParentSpecialtyId(artTypeService.getParent(record.getSpecialtyId()));
             record = programmeRepo.save(record);
             record = programmeRepo.save(record);
         }
         }
@@ -126,6 +127,28 @@ public class ProgrammeService {
         return record;
         return record;
     }
     }
 
 
+    public Page<Programme> all2(PageQuery pageQuery) {
+        Map<String, Object> query = pageQuery.getQuery();
+        Object code = query.get("code");
+        String artCode = null;
+        if (ObjectUtil.isNotNull(code)) {
+            artCode = Convert.convert(String.class, code);
+            query.remove("code");
+        }
+
+        List<ArtType> artTypes = artTypeRepo.findAll();
+
+        String finalArtCode = artCode;
+        return programmeRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
+            List<Predicate> and = JpaUtils.toPredicates(pageQuery, Programme.class, root, criteriaQuery, criteriaBuilder);
+            if (StrUtil.isNotBlank(finalArtCode)) {
+                and.add(root.get("specialtyId").in(artTypeService.getIds(artTypes, finalArtCode)));
+            }
+            return criteriaBuilder.and(and.toArray(new Predicate[0]));
+
+        }), JpaUtils.toPageRequest(pageQuery));
+    }
+
 
 
     public Page<ProgrammeDTO> backAll(PageQuery pageQuery) {
     public Page<ProgrammeDTO> backAll(PageQuery pageQuery) {
         Map<String, Object> query = pageQuery.getQuery();
         Map<String, Object> query = pageQuery.getQuery();
@@ -139,7 +162,7 @@ public class ProgrammeService {
         List<ArtType> artTypes = artTypeRepo.findAll();
         List<ArtType> artTypes = artTypeRepo.findAll();
 
 
         String finalArtCode = artCode;
         String finalArtCode = artCode;
-        Page<Programme> all = programmeRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
+        Page<Programme> all =  programmeRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
             List<Predicate> and = JpaUtils.toPredicates(pageQuery, Programme.class, root, criteriaQuery, criteriaBuilder);
             List<Predicate> and = JpaUtils.toPredicates(pageQuery, Programme.class, root, criteriaQuery, criteriaBuilder);
             if (StrUtil.isNotBlank(finalArtCode)) {
             if (StrUtil.isNotBlank(finalArtCode)) {
                 and.add(root.get("specialtyId").in(artTypeService.getIds(artTypes, finalArtCode)));
                 and.add(root.get("specialtyId").in(artTypeService.getIds(artTypes, finalArtCode)));
@@ -241,135 +264,177 @@ public class ProgrammeService {
     }
     }
 
 
     @Transactional(rollbackOn = Exception.class)
     @Transactional(rollbackOn = Exception.class)
-    public void upload(MultipartFile file, Long userId) throws IOException {
+    public void upload(MultipartFile file, Long userId) throws Exception {
         Organization organization = organizationRepo.findByUserId(userId).orElseThrow(new BusinessException("无记录"));
         Organization organization = organizationRepo.findByUserId(userId).orElseThrow(new BusinessException("无记录"));
-        Long performance = performanceRepo.findNow(LocalDate.now());
-        if (ObjectUtil.isNull(performance)) {
-            throw new BusinessException("没有正在报名中的展演活动");
-        }
-
-        File destDir = TempFile.createTempDirectory("import");
-        ZipUtil.unzip(file.getInputStream(), destDir, StandardCharsets.UTF_8);
-
-//        File xlsxFile = FileUtils.findExcel1(destDir);
-//        if (xlsxFile == null) {
-//            Map<String, File> map = FileUtils.findExcel(destDir);
-//            if (map == null) return;
-//
-//            xlsxFile = map.get("file");
-//            destDir = map.get("destDir");
+//        Long performance = performanceRepo.findNow(LocalDate.now());
+//        if (ObjectUtil.isNull(performance)) {
+//            throw new BusinessException("没有正在报名中的展演活动");
 //        }
 //        }
-        File xlsxFile = FileUtils.folderMethod1(destDir, null);
-        if (xlsxFile == null) {
-            return;
-        }
-        InputStream indicatorStream = new FileInputStream(xlsxFile);
-        UploadDataListener<ProgUploadDTO> listener = new UploadDataListener<>();
-        List<ProgUploadDTO> dtos = EasyExcel.read(indicatorStream, ProgUploadDTO.class, listener).sheet().doReadSync();
 
 
-//        Map<String, Long> performanceMap = performanceRepo.findAll()
-//                .stream()
-//                .collect(Collectors.toMap(Performance::getName, Performance::getId));
+        // 临时开启
+        Long performance = performanceRepo.findByYear(String.valueOf(LocalDate.now().getYear())).getId();
 
 
-        Map<Integer, Map<String, Long>> mapMap = settingRepo.findAllByFlagIn(CollUtil.newArrayList(3, 4))
-                .stream()
-                .collect(Collectors.groupingBy(Setting::getFlag, Collectors.toMap(Setting::getName, Setting::getId)));
+        File destDir = TempFile.createTempDirectory("import");
+        try {
 
 
-        Map<String, Long> gradeMap = gradingOrganizationRepo.findAll()
-                .stream()
-                .collect(Collectors.toMap(GradingOrganization::getName, GradingOrganization::getId));
 
 
-        Map<String, ArtType> artTypeMap = artTypeRepo.findAll()
-                .stream()
-                .collect(Collectors.toMap(ArtType::getName, artType -> artType));
-
-
-        List<Participant> participants = new ArrayList<>();
-        Long pid = null;
-        for (ProgUploadDTO dto : dtos) {
-            if (dto.getName() != null && dto.getSpecialty() != null) {
-                Programme programme = new Programme(dto);
-                ArtType specialty = artTypeMap.get(dto.getSpecialty());
-                programme.setOrganizationId(organization.getId());
-                programme.setGradingOrganizationId(gradeMap.get(dto.getGradingOrganization()));
-                programme.setPerformanceId(performance);
-                programme.setSpecialtyId(specialty.getId());
-                String level = dto.getLevel();
-                if (StrUtil.isNotBlank(level)) {
-                    level = level.substring(0, 2);
-                }
-                if (dto.getCompetitionGroup().equals(CompetitionGroup.SINGLE)) {
-                    programme.setLevelSettingId(mapMap.get(3).get(level));
-                } else if (dto.getCompetitionGroup().equals(CompetitionGroup.COLLECTIVE)) {
-                    programme.setLevelSettingId(mapMap.get(4).get(level));
+            String originalFilename = file.getOriginalFilename();
+            boolean zip = Pattern.matches("zip", FilenameUtils.getExtension(originalFilename));
+            boolean rar = false;
+            if (!zip) {
+                rar = Pattern.matches("rar", FilenameUtils.getExtension(originalFilename));
+            }
+            try {
+                if (rar) {
+                    FileUtils.unrar(file.getInputStream(), destDir);
+                } else if (zip) {
+                    try {
+                        ZipUtil.unzip(file.getInputStream(), destDir, StandardCharsets.UTF_8);
+                    } catch (Exception e) {
+                        ZipUtil.unzip(file.getInputStream(), destDir, Charset.forName("gbk"));
+                    }
                 }
                 }
+            } catch (Exception e) {
+                throw new BusinessException("最能上传zip或者rar压缩包");
+            }
 
 
-                File uploadFile = FileUtils.folderMethod1(destDir, dto.getName());
-                if (dto.getVideo() != null) {
-//                    File uploadFile = new File(destDir, dto.getVideo());
-                    uploadFile = FileUtils.folderMethod1(destDir, dto.getVideo());
-                }
-                if (ObjectUtil.isNotNull(uploadFile) && uploadFile.exists()) {
-                    // 视频
-                    if (!specialty.getCode().startsWith("03")) {
-                        // 上传
-                        String videoPath = "video/" + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date())
-                                + RandomStringUtils.randomAlphabetic(8)
-                                + "." + FilenameUtils.getExtension(uploadFile.getName());
-                        String url = storageService.uploadFromInputStream(new FileInputStream(uploadFile), videoPath);
-                        VideoObject vo = new VideoObject();
-                        vo.setSrc(url);
-                        programme.setVideo(vo);
+
+            File xlsxFile = FileUtils.findInDir(destDir, null);
+            if (xlsxFile == null) {
+                return;
+            }
+            InputStream indicatorStream = new FileInputStream(xlsxFile);
+            UploadDataListener<ProgUploadDTO> listener = new UploadDataListener<>();
+            List<ProgUploadDTO> dtos = EasyExcel.read(indicatorStream, ProgUploadDTO.class, listener)
+                    .sheet()
+                    .doReadSync();
+
+            Map<Integer, Map<String, Long>> mapMap = settingRepo.findAllByFlagIn(CollUtil.newArrayList(3, 4))
+                    .stream()
+                    .collect(Collectors.groupingBy(Setting::getFlag, Collectors.toMap(Setting::getName, Setting::getId)));
+
+            Map<String, Long> gradeMap = gradingOrganizationRepo.findAll()
+                    .stream()
+                    .collect(Collectors.toMap(GradingOrganization::getName, GradingOrganization::getId));
+
+            Map<String, ArtType> artTypeMap = artTypeRepo.findAll()
+                    .stream()
+                    .collect(Collectors.toMap(ArtType::getName, artType -> artType));
+
+
+            List<Participant> participants = new ArrayList<>();
+            Long pid = null;
+            for (ProgUploadDTO dto : dtos) {
+                if (dto.getName() != null && dto.getSpecialty() != null) {
+                    Programme programme = new Programme(dto);
+                    ArtType specialty = artTypeMap.get(dto.getSpecialty());
+                    programme.setOrganizationId(organization.getId());
+                    programme.setGradingOrganizationId(gradeMap.get(dto.getGradingOrganization()));
+                    programme.setPerformanceId(performance);
+
+                    // 专业
+                    if (ObjectUtil.isNotNull(specialty)) {
+                        programme.setSpecialtyId(specialty.getId());
                     } else {
                     } else {
-                        // 图片
-                        programme.setAnnex(this.saveImg(uploadFile));
+                        throw new BusinessException("专业名称不正确,仔细核对专业表");
                     }
                     }
 
 
-                }
+                    // 节目状态
+                    programme.setProgrammeStatus(ProgrammeStatus.INITIAL);
+                    String level = dto.getLevel();
+                    if (StrUtil.isNotBlank(level)) {
+                        level = level.substring(0, 2);
+                    }
+                    if (dto.getCompetitionGroup().equals(CompetitionGroup.SINGLE)) {
+                        programme.setLevelSettingId(mapMap.get(3).get(level));
+                    } else if (dto.getCompetitionGroup().equals(CompetitionGroup.COLLECTIVE)) {
+                        programme.setLevelSettingId(mapMap.get(4).get(level));
+                    }
 
 
-                pid = programmeRepo.save(programme).getId();
-            }
+                    File uploadFile = FileUtils.findInDir(destDir, dto.getName());
+                    if (dto.getVideo() != null) {
+                        uploadFile = FileUtils.findInDir(destDir, dto.getVideo());
+                    }
+                    if (ObjectUtil.isNotNull(uploadFile) && uploadFile.exists()) {
+                        // 视频
+                        if (ObjectUtil.isNotNull(specialty)) {
+                            if (!specialty.getCode().startsWith("03")) {
+                                // 上传
+                                String videoPath = "video/" + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date())
+                                        + RandomStringUtils.randomAlphabetic(8)
+                                        + "." + FilenameUtils.getExtension(uploadFile.getName());
+                                String url = storageService.uploadFromInputStream(new FileInputStream(uploadFile), videoPath);
+                                VideoObject vo = new VideoObject();
+                                vo.setSrc(url);
+                                programme.setVideo(vo);
+                            } else {
+                                // 图片
+                                programme.setAnnex(this.saveImg(uploadFile));
+                            }
+                        }
 
 
-            Participant participant = new Participant(dto);
-            if (ObjectUtil.isNotNull(dto.getParticipantBirthday())) {
-                if (dto.getParticipantBirthday().contains("/")) {
-                    LocalDate birthday = LocalDate.parse(dto.getParticipantBirthday(), DateTimeFormatter.ofPattern(DateConfig.DEFAULT_DATE_FORMAT1));
-                    participant.setBirthday(birthday);
-                } else if (dto.getParticipantBirthday().contains("-")) {
-                    LocalDate birthday = LocalDate.parse(dto.getParticipantBirthday(), DateTimeFormatter.ofPattern(DateConfig.DEFAULT_DATE_FORMAT));
-                    participant.setBirthday(birthday);
-                } else {
-                    throw new BusinessException("日期格式错误!");
+
+                    }
+
+                    pid = programmeRepo.save(programme).getId();
                 }
                 }
 
 
+                Participant participant = new Participant(dto);
+                if (ObjectUtil.isNotNull(dto.getParticipantBirthday())) {
+                    if (dto.getParticipantBirthday().contains("/")) {
+                        try {
+                            LocalDate birthday = LocalDate.parse(dto.getParticipantBirthday(), DateTimeFormatter.ofPattern(DateConfig.DEFAULT_DATE_FORMAT1));
+                            participant.setBirthday(birthday);
+                        } catch (Exception e) {
+                            throw new BusinessException("日期格式错误");
+                        }
+
+                    } else if (dto.getParticipantBirthday().contains("-")) {
+                        try {
+                            LocalDate birthday = LocalDate.parse(dto.getParticipantBirthday(), DateTimeFormatter.ofPattern(DateConfig.DEFAULT_DATE_FORMAT));
+                            participant.setBirthday(birthday);
+                        } catch (Exception e) {
+                            throw new BusinessException("日期格式错误");
+                        }
+                    } else {
+                        throw new BusinessException("日期格式错误!");
+                    }
+
 
 
-            }
+                }
 
 
-            participant.setProgrammeId(pid);
-            participants.add(participant);
-            File uploadImg;
-            if (dto.getImg() != null) {
+                participant.setProgrammeId(pid);
+                participant.setPerformanceId(performance);
+                participants.add(participant);
+                File uploadImg;
+                if (dto.getImg() != null) {
 //                File uploadFile = new File(destDir, dto.getImg());
 //                File uploadFile = new File(destDir, dto.getImg());
-                uploadImg = FileUtils.folderMethod1(destDir, dto.getImg());
-            } else {
-                uploadImg = FileUtils.folderMethod1(destDir, dto.getIdNo() + "证件照");
-            }
-            if (ObjectUtil.isNotNull(uploadImg) && uploadImg.exists()) {
-                participant.setImg(this.saveImg(uploadImg));
-            }
+                    uploadImg = FileUtils.findInDir(destDir, dto.getImg());
+                } else {
+                    uploadImg = FileUtils.findInDir(destDir, dto.getIdNo() + "证件照");
+                }
+                if (ObjectUtil.isNotNull(uploadImg) && uploadImg.exists()) {
+                    participant.setImg(this.saveImg(uploadImg));
+                }
 
 
-            File uploadCertificate;
-            if (dto.getCertificate() != null) {
-                uploadCertificate = FileUtils.folderMethod1(destDir, dto.getCertificate());
-            } else {
-                uploadCertificate = FileUtils.folderMethod1(destDir, dto.getIdNo() + "证书");
-            }
-            if (ObjectUtil.isNotNull(uploadCertificate) && uploadCertificate.exists()) {
-                participant.setCertificate(this.saveImg(uploadCertificate));
+                File uploadCertificate;
+                if (dto.getCertificate() != null) {
+                    uploadCertificate = FileUtils.findInDir(destDir, dto.getCertificate());
+                } else {
+                    uploadCertificate = FileUtils.findInDir(destDir, dto.getIdNo() + "证书");
+                }
+                if (ObjectUtil.isNotNull(uploadCertificate) && uploadCertificate.exists()) {
+                    participant.setCertificate(this.saveImg(uploadCertificate));
+                }
             }
             }
-        }
 
 
-        participantRepo.saveAll(participants);
+            participantRepo.saveAll(participants);
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            FileUtils.delFiles(destDir);
+
+        }
     }
     }
 
 
     private String saveImg(File uploadFile) throws FileNotFoundException {
     private String saveImg(File uploadFile) throws FileNotFoundException {
@@ -562,19 +627,19 @@ public class ProgrammeService {
             List<Programme> programmes = programmeRepo.findAllByPerformanceIdAndProgrammeStatusAndReviewArrangeIdIsNull(performanceId, ProgrammeStatus.SUBMIT);
             List<Programme> programmes = programmeRepo.findAllByPerformanceIdAndProgrammeStatusAndReviewArrangeIdIsNull(performanceId, ProgrammeStatus.SUBMIT);
             if (CollUtil.isNotEmpty(programmes)) {
             if (CollUtil.isNotEmpty(programmes)) {
                 this.sort(programmes);
                 this.sort(programmes);
-                return this.toShowDTOList(programmes, performance.getName());
+                return this.toShowDTOList(programmes);
             }
             }
             return null;
             return null;
         }
         }
         List<Programme> programmes = programmeRepo.findAllByPerformanceIdAndProgrammeStatusAndArrangeIdIsNull(performanceId, ProgrammeStatus.SUBMIT);
         List<Programme> programmes = programmeRepo.findAllByPerformanceIdAndProgrammeStatusAndArrangeIdIsNull(performanceId, ProgrammeStatus.SUBMIT);
         if (CollUtil.isNotEmpty(programmes)) {
         if (CollUtil.isNotEmpty(programmes)) {
             this.sort(programmes);
             this.sort(programmes);
-            return this.toShowDTOList(programmes, performance.getName());
+            return this.toShowDTOList(programmes);
         }
         }
         return null;
         return null;
     }
     }
 
 
-    private List<ProgrammeShowDTO> toShowDTOList(List<Programme> programmes, String name) {
+    public List<ProgrammeShowDTO> toShowDTOList(List<Programme> programmes) {
         Map<Long, String> settingMap = settingRepo.findAllByFlagIn(CollUtil.newArrayList(3, 4))
         Map<Long, String> settingMap = settingRepo.findAllByFlagIn(CollUtil.newArrayList(3, 4))
                 .stream()
                 .stream()
                 .collect(Collectors.toMap(Setting::getId, Setting::getName));
                 .collect(Collectors.toMap(Setting::getId, Setting::getName));

+ 30 - 0
src/main/java/com/izouma/wenlvju/service/storage/AliStorageService.java

@@ -1,6 +1,10 @@
 package com.izouma.wenlvju.service.storage;
 package com.izouma.wenlvju.service.storage;
 
 
+import com.aliyun.oss.OSS;
 import com.aliyun.oss.OSSClient;
 import com.aliyun.oss.OSSClient;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.model.CopyObjectRequest;
+import com.aliyun.oss.model.CopyObjectResult;
 import com.aliyun.oss.model.ObjectMetadata;
 import com.aliyun.oss.model.ObjectMetadata;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.exception.BusinessException;
 import lombok.Data;
 import lombok.Data;
@@ -67,4 +71,30 @@ public class AliStorageService implements StorageService {
         return ossDomain + "/" + path;
         return ossDomain + "/" + path;
     }
     }
 
 
+    public void rename(String sourceKey, String destinationKey) {
+        // 填写源Object的完整路径。Object完整路径中不能包含Bucket名称。
+//        String sourceKey = "application.txt";
+
+        // 填写目标Object的完整路径。Object完整路径中不能包含Bucket名称。
+//        String destinationKey = sourceKey;
+
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(ossEndPoint, accessKeyId, accessKeySecret);
+
+        // 创建CopyObjectRequest对象。
+        CopyObjectRequest copyObjectRequest = new CopyObjectRequest(ossBucketName, sourceKey, ossBucketName, destinationKey);
+
+        // 设置新的文件元信息。
+        ObjectMetadata meta = new ObjectMetadata();
+//        meta.setContentType("text/txt");
+        copyObjectRequest.setNewObjectMetadata(meta);
+
+        // 复制文件。
+        CopyObjectResult result = ossClient.copyObject(copyObjectRequest);
+        System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
+
+        // 关闭OSSClient。
+        ossClient.shutdown();
+    }
+
 }
 }

+ 116 - 31
src/main/java/com/izouma/wenlvju/utils/FileUtils.java

@@ -1,7 +1,13 @@
 package com.izouma.wenlvju.utils;
 package com.izouma.wenlvju.utils;
 
 
-import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.StrUtil;
+import com.github.junrar.Archive;
+import com.github.junrar.exception.RarException;
+import com.github.junrar.rarfile.FileHeader;
+import com.izouma.wenlvju.exception.BusinessException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
 
 
 import java.io.*;
 import java.io.*;
@@ -12,7 +18,10 @@ import java.nio.file.attribute.PosixFileAttributes;
 import java.nio.file.attribute.PosixFilePermission;
 import java.nio.file.attribute.PosixFilePermission;
 import java.nio.file.attribute.PosixFilePermissions;
 import java.nio.file.attribute.PosixFilePermissions;
 import java.util.*;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 
+@Slf4j
 public class FileUtils {
 public class FileUtils {
 
 
     public static String getExtension(String fileName) {
     public static String getExtension(String fileName) {
@@ -202,43 +211,57 @@ public class FileUtils {
 
 
     }
     }
 
 
+    public static File findInDir(File dir, String fileName) {
+        if (dir.isDirectory()) {
+            for (File file : dir.listFiles()) {
+                if (file.isDirectory()) {
+                    File f = findInDir(file, fileName);
+                    if (f != null) {
+                        return f;
+                    }
+                } else {
+                    if (fileName != null) {
+                        if (file.getName().contains(fileName)) {
+                            return file;
+                        }
 
 
-    public static Map<String, File> findExcel(File dir) {
-        if (!(dir.exists() && dir.isDirectory())) return null;
-        for (File file : dir.listFiles()) {
-            String name = file.getName().toLowerCase();
-            if ((name.endsWith(".xlsx") || name.endsWith(".xls")) && !name.startsWith(".") && !file.isHidden()) {
-                Map<String, File> fileMap = new HashMap<>();
-                fileMap.put("file", file);
-                fileMap.put("destDir", dir);
-                return fileMap;
-            } else if (file.isDirectory() && !file.isHidden()) {
-                return findExcel(file);
+                    } else if (!file.isHidden() && Pattern.matches("xls|xlsx", FilenameUtils.getExtension(file.getName()))) {
+                        return file;
+                    }
+                }
             }
             }
-        }
-        return null;
-    }
-
-    public static File findByName(File dir, String fileName) {
-        if (!(dir.exists() && dir.isDirectory())) return null;
-        for (File file : dir.listFiles()) {
-            String name = file.getName().toLowerCase();
-            if (name.contains(fileName)) {
-                return file;
+        } else if (fileName != null) {
+            if (dir.getName().contains(fileName)) {
+                return dir;
             }
             }
+
+        } else if (!dir.isHidden() && Pattern.matches("xls|xlsx", FilenameUtils.getExtension(dir.getName()))) {
+            return dir;
         }
         }
         return null;
         return null;
     }
     }
 
 
-    public static File findExcel1(File dir) {
-        if (!(dir.exists() && dir.isDirectory())) return null;
-        for (File file : dir.listFiles()) {
-            String name = file.getName().toLowerCase();
-            if ((name.endsWith(".xlsx") || name.endsWith(".xls")) && !name.startsWith(".") && !file.isHidden()) {
-                return file;
+    public static boolean delFiles(File file) {
+        try {
+            boolean result;
+            //目录
+            if (file.isDirectory()) {
+                 File[] childrenFiles = file.listFiles();
+
+                for (File childFile : childrenFiles) {
+                    result = delFiles(childFile);
+                    if (!result) {
+                        return result;
+                    }
+                }
             }
             }
+            //删除 文件、空目录
+            result = file.delete();
+            return result;
+        } catch (Exception e) {
+            log.error("删除失败", e);
         }
         }
-        return null;
+        return false;
     }
     }
 
 
     public static File folderMethod1(File file, String fileName) {
     public static File folderMethod1(File file, String fileName) {
@@ -248,7 +271,9 @@ public class FileUtils {
             if (null == file.listFiles()) {
             if (null == file.listFiles()) {
                 return null;
                 return null;
             }
             }
-            list.addAll(Arrays.asList(file.listFiles()));
+
+            list.addAll(CollUtil.newArrayList(file.listFiles()));
+
             while (!list.isEmpty()) {
             while (!list.isEmpty()) {
                 File[] files = list.removeFirst().listFiles();
                 File[] files = list.removeFirst().listFiles();
                 if (null == files) {
                 if (null == files) {
@@ -264,7 +289,7 @@ public class FileUtils {
                                 return f;
                                 return f;
                             }
                             }
                         } else {
                         } else {
-                            if ((name.endsWith(".xlsx") || name.endsWith(".xls")) && !name.startsWith(".") && !file.isHidden()) {
+                            if ((name.endsWith(".xlsx") || name.endsWith(".xls")) && !name.startsWith(".") && !f.isHidden()) {
                                 return f;
                                 return f;
                             }
                             }
                         }
                         }
@@ -275,4 +300,64 @@ public class FileUtils {
         }
         }
         return null;
         return null;
     }
     }
+
+    public static void unrar(InputStream sourceRar, File destDir) throws Exception {
+        Archive archive = null;
+        FileOutputStream fos = null;
+        System.out.println("Starting 开始解压...");
+        try {
+            archive = new Archive(sourceRar);
+            FileHeader fh = archive.nextFileHeader();
+            File destFileName;
+            while (fh != null) {
+
+                //中文名称乱码
+                String fileName = fh.getFileNameW().replaceAll("/", File.separator).replaceAll("\\\\", File.separator);
+                if (StringUtils.isBlank(fileName)) {
+                    fileName = fh.getFileNameString()
+                            .replaceAll("/", File.separator)
+                            .replaceAll("\\\\", File.separator);
+                }
+
+//                String compressFileName = fh.getFileNameString().trim();
+                destFileName = new File(destDir.getAbsolutePath() + "/" + fileName);
+                if (fh.isDirectory()) {
+                    if (!destFileName.exists()) {
+                        destFileName.mkdirs();
+                    }
+                    fh = archive.nextFileHeader();
+                    continue;
+                }
+                if (!destFileName.getParentFile().exists()) {
+                    destFileName.getParentFile().mkdirs();
+                }
+
+                fos = new FileOutputStream(destFileName);
+                archive.extractFile(fh, fos);
+                fos.close();
+                fos = null;
+                fh = archive.nextFileHeader();
+            }
+
+            archive.close();
+            archive = null;
+            System.out.println("解压完毕...");
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            if (fos != null) {
+                try {
+                    fos.close();
+                } catch (Exception e) {
+                }
+            }
+            if (archive != null) {
+                try {
+                    archive.close();
+                } catch (Exception e) {
+                }
+            }
+        }
+    }
+
 }
 }

+ 60 - 0
src/main/java/com/izouma/wenlvju/web/AnnouncementController.java

@@ -0,0 +1,60 @@
+package com.izouma.wenlvju.web;
+import com.izouma.wenlvju.domain.Announcement;
+import com.izouma.wenlvju.service.AnnouncementService;
+import com.izouma.wenlvju.dto.PageQuery;
+import com.izouma.wenlvju.exception.BusinessException;
+import com.izouma.wenlvju.repo.AnnouncementRepo;
+import com.izouma.wenlvju.utils.ObjUtils;
+import com.izouma.wenlvju.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/announcement")
+@AllArgsConstructor
+public class AnnouncementController extends BaseController {
+    private AnnouncementService announcementService;
+    private AnnouncementRepo announcementRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public Announcement save(@RequestBody Announcement record) {
+        if (record.getId() != null) {
+            Announcement orig = announcementRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+            return announcementRepo.save(orig);
+        }
+        return announcementRepo.save(record);
+    }
+
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<Announcement> all(@RequestBody PageQuery pageQuery) {
+        return announcementService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public Announcement get(@PathVariable Long id) {
+        return announcementRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        announcementRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<Announcement> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+}
+

+ 11 - 1
src/main/java/com/izouma/wenlvju/web/AuthenticationController.java

@@ -19,6 +19,7 @@ import org.springframework.security.core.Authentication;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 
 
 import java.util.Map;
 import java.util.Map;
@@ -35,7 +36,8 @@ public class AuthenticationController {
 
 
     @PostMapping("/login")
     @PostMapping("/login")
     public String loginByUserPwd(String username, String password, Integer expiration) {
     public String loginByUserPwd(String username, String password, Integer expiration) {
-        Authentication authentication = authenticate(username, password);
+        String account = userService.byPhone(username);
+        Authentication authentication = authenticate(account, password);
         JwtUser jwtUser = (JwtUser) authentication.getPrincipal();
         JwtUser jwtUser = (JwtUser) authentication.getPrincipal();
         return jwtTokenUtil.generateToken(jwtUser);
         return jwtTokenUtil.generateToken(jwtUser);
 
 
@@ -57,6 +59,9 @@ public class AuthenticationController {
         try {
         try {
             User user = userService.loginByPhone(phone);
             User user = userService.loginByPhone(phone);
             return jwtTokenUtil.generateToken(JwtUserFactory.create(user));
             return jwtTokenUtil.generateToken(JwtUserFactory.create(user));
+        } catch (NullPointerException e) {
+            log.error("loginByPhone", e);
+            throw new AuthenticationException("该手机号未注册", e);
         } catch (Exception e) {
         } catch (Exception e) {
             log.error("loginByPhone", e);
             log.error("loginByPhone", e);
             throw new AuthenticationException("登陆错误", e);
             throw new AuthenticationException("登陆错误", e);
@@ -103,4 +108,9 @@ public class AuthenticationController {
             throw new AuthenticationException("用户名或密码错误", e);
             throw new AuthenticationException("用户名或密码错误", e);
         }
         }
     }
     }
+
+    @PostMapping("/forgetPW")
+    public void forgetPassword(@RequestParam String name, @RequestParam String phone, @RequestParam String password) {
+        userService.forgetPassword(name, phone, password);
+    }
 }
 }

+ 6 - 3
src/main/java/com/izouma/wenlvju/web/GradingOrganizationController.java

@@ -1,5 +1,7 @@
 package com.izouma.wenlvju.web;
 package com.izouma.wenlvju.web;
+
 import com.izouma.wenlvju.domain.GradingOrganization;
 import com.izouma.wenlvju.domain.GradingOrganization;
+import com.izouma.wenlvju.enums.GradingOrganizationDTO;
 import com.izouma.wenlvju.service.GradingOrganizationService;
 import com.izouma.wenlvju.service.GradingOrganizationService;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.exception.BusinessException;
@@ -20,13 +22,14 @@ import java.util.List;
 @AllArgsConstructor
 @AllArgsConstructor
 public class GradingOrganizationController extends BaseController {
 public class GradingOrganizationController extends BaseController {
     private GradingOrganizationService gradingOrganizationService;
     private GradingOrganizationService gradingOrganizationService;
-    private GradingOrganizationRepo gradingOrganizationRepo;
+    private GradingOrganizationRepo    gradingOrganizationRepo;
 
 
     @PreAuthorize("hasRole('ADMIN')")
     @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
     @PostMapping("/save")
     public GradingOrganization save(@RequestBody GradingOrganization record) {
     public GradingOrganization save(@RequestBody GradingOrganization record) {
         if (record.getId() != null) {
         if (record.getId() != null) {
-            GradingOrganization orig = gradingOrganizationRepo.findById(record.getId()).orElseThrow(new BusinessException("无记录"));
+            GradingOrganization orig = gradingOrganizationRepo.findById(record.getId())
+                    .orElseThrow(new BusinessException("无记录"));
             ObjUtils.merge(orig, record);
             ObjUtils.merge(orig, record);
             return gradingOrganizationRepo.save(orig);
             return gradingOrganizationRepo.save(orig);
         }
         }
@@ -54,7 +57,7 @@ public class GradingOrganizationController extends BaseController {
     @GetMapping("/excel")
     @GetMapping("/excel")
     @ResponseBody
     @ResponseBody
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
     public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
-        List<GradingOrganization> data = all(pageQuery).getContent();
+        List<GradingOrganizationDTO> data = all(pageQuery).map(GradingOrganizationDTO::new).getContent();
         ExcelUtils.export(response, data);
         ExcelUtils.export(response, data);
     }
     }
 }
 }

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

@@ -137,12 +137,13 @@ public class RateController extends BaseController {
     }
     }
 
 
     @GetMapping(value = "/exportPdf/{id}", produces = "application/pdf;charset=utf-8")
     @GetMapping(value = "/exportPdf/{id}", produces = "application/pdf;charset=utf-8")
-    public void exportPdf(@PathVariable Long id, HttpServletResponse response) {
+    public byte[] exportPdf(@PathVariable Long id, HttpServletResponse response) {
         try {
         try {
-            rateService.exportPdf(id, response);
+            return rateService.exportPdf(id, response);
         } catch (IOException e) {
         } catch (IOException e) {
             e.printStackTrace();
             e.printStackTrace();
         }
         }
+        return null;
     }
     }
 
 
     @OperLog(value = "等级评定", type = "修改", desc = "对等级评定申请进行操作")
     @OperLog(value = "等级评定", type = "修改", desc = "对等级评定申请进行操作")
@@ -181,10 +182,23 @@ public class RateController extends BaseController {
         return rateRepo.countAllByOrganizationIdAndYear(id, year) == 0;
         return rateRepo.countAllByOrganizationIdAndYear(id, year) == 0;
     }
     }
 
 
+    @ApiOperation("提交纸质材料")
     @PostMapping("/paperMaterial")
     @PostMapping("/paperMaterial")
     public void paperMaterial(@RequestParam Long id, @RequestParam RateStatus status, String remark) {
     public void paperMaterial(@RequestParam Long id, @RequestParam RateStatus status, String remark) {
         rateService.paperMaterial(id, status, remark, SecurityUtils.getAuthenticatedUser().getId());
         rateService.paperMaterial(id, status, remark, SecurityUtils.getAuthenticatedUser().getId());
     }
     }
 
 
+    @ApiOperation("批量发送短信")
+    @PostMapping("/batchSendSms")
+    public void batchSendSms(boolean announcement) {
+        rateService.batchSendSms(announcement);
+    }
+
+    @ApiOperation("设置等级比例")
+    @PostMapping("/gradeRatio")
+    public void gradeRatio(double excellent, double eligible) {
+        rateService.gradeRatio(excellent, eligible, SecurityUtils.getAuthenticatedUser().getId());
+    }
+
 }
 }
 
 

+ 1 - 1
src/main/java/com/izouma/wenlvju/web/RateExpertAuditController.java

@@ -52,7 +52,7 @@ public class RateExpertAuditController extends BaseController {
 
 
     @PostMapping("/grade")
     @PostMapping("/grade")
     public void grade(Long rateId) {
     public void grade(Long rateId) {
-        rateExpertAuditService.grade(rateId, SecurityUtils.getAuthenticatedUser().getId());
+        rateExpertAuditService.grade(rateId);
     }
     }
 
 
 
 

+ 102 - 0
src/main/java/com/izouma/wenlvju/web/TrainingInstitutionController.java

@@ -0,0 +1,102 @@
+package com.izouma.wenlvju.web;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.izouma.wenlvju.domain.TrainingInstitution;
+import com.izouma.wenlvju.dto.PageQuery;
+import com.izouma.wenlvju.dto.TrainingInstitutionDTO;
+import com.izouma.wenlvju.exception.BusinessException;
+import com.izouma.wenlvju.repo.TrainingInstitutionRepo;
+import com.izouma.wenlvju.service.TrainingInstitutionService;
+import com.izouma.wenlvju.utils.ObjUtils;
+import com.izouma.wenlvju.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/trainingInstitution")
+@AllArgsConstructor
+public class TrainingInstitutionController extends BaseController {
+    private TrainingInstitutionService trainingInstitutionService;
+    private TrainingInstitutionRepo    trainingInstitutionRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public TrainingInstitution save(@RequestBody TrainingInstitution record) {
+        if (record.getId() != null) {
+            TrainingInstitution orig = trainingInstitutionRepo.findById(record.getId())
+                    .orElseThrow(new BusinessException("无记录"));
+            ObjUtils.merge(orig, record);
+
+            orig.setSubmit(true);
+            if (ObjectUtil.isNull(orig.getFirstWrite())) {
+                orig.setFirstWrite(LocalDateTime.now());
+            }
+            return trainingInstitutionRepo.save(orig);
+        }
+        return trainingInstitutionRepo.save(record);
+    }
+
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/all")
+    public Page<TrainingInstitution> all(@RequestBody PageQuery pageQuery) {
+        return trainingInstitutionService.all(pageQuery);
+    }
+
+    @GetMapping("/get/{id}")
+    public TrainingInstitution get(@PathVariable Long id) {
+        return trainingInstitutionRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        trainingInstitutionRepo.softDelete(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<TrainingInstitution> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
+    @GetMapping("/excel1")
+    @ResponseBody
+    public void excel1(HttpServletResponse response) throws IOException {
+        List<TrainingInstitution> data = trainingInstitutionRepo.findAllByPhoneIsNull();
+        List<TrainingInstitutionDTO> dtos = data.stream()
+                .map(TrainingInstitutionDTO::new)
+                .collect(Collectors.toList());
+        ExcelUtils.export(response, dtos);
+    }
+
+    @GetMapping("/batchSend")
+    public void batchSend() throws InterruptedException {
+        List<String> phones = trainingInstitutionRepo.findAllBySubmitFalseAndPhoneIsNotNull();
+        trainingInstitutionService.batchSend(phones);
+    }
+
+    @PostMapping("/upload")
+    public void uploadFile(@RequestParam("file") MultipartFile file) throws Exception {
+        trainingInstitutionService.upload(file);
+    }
+
+    @PostMapping("/name")
+    public Page<String> name(@RequestBody PageQuery pageQuery) {
+        return trainingInstitutionService.all(pageQuery).map(TrainingInstitution::getName);
+    }
+
+    @PostMapping("/byUscc")
+    public TrainingInstitution byUscc(@RequestParam String name, @RequestParam String uscc) {
+        return trainingInstitutionService.byUscc(name, uscc);
+    }
+}
+

+ 29 - 7
src/main/java/com/izouma/wenlvju/web/performance/ProgrammeController.java

@@ -7,6 +7,7 @@ import com.izouma.wenlvju.dto.*;
 import com.izouma.wenlvju.enums.ProgrammeStatus;
 import com.izouma.wenlvju.enums.ProgrammeStatus;
 import com.izouma.wenlvju.enums.SignedIn;
 import com.izouma.wenlvju.enums.SignedIn;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.exception.BusinessException;
+import com.izouma.wenlvju.repo.performance.ParticipantRepo;
 import com.izouma.wenlvju.repo.performance.PerformanceRepo;
 import com.izouma.wenlvju.repo.performance.PerformanceRepo;
 import com.izouma.wenlvju.repo.performance.ProgrammeRepo;
 import com.izouma.wenlvju.repo.performance.ProgrammeRepo;
 import com.izouma.wenlvju.service.UserService;
 import com.izouma.wenlvju.service.UserService;
@@ -18,6 +19,7 @@ import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.MultipartFile;
@@ -37,6 +39,7 @@ public class ProgrammeController extends BaseController {
     private ProgrammeRepo    programmeRepo;
     private ProgrammeRepo    programmeRepo;
     private UserService      userService;
     private UserService      userService;
     private PerformanceRepo  performanceRepo;
     private PerformanceRepo  performanceRepo;
+    private ParticipantRepo  participantRepo;
 
 
     //@PreAuthorize("hasRole('ADMIN')")
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
     @PostMapping("/save")
@@ -82,6 +85,8 @@ public class ProgrammeController extends BaseController {
     @PostMapping("/del/{id}")
     @PostMapping("/del/{id}")
     public void del(@PathVariable Long id) {
     public void del(@PathVariable Long id) {
         programmeRepo.softDelete(id);
         programmeRepo.softDelete(id);
+        // 删除参演人员
+        participantRepo.softDeleteProgrammeId(id);
     }
     }
 
 
     @GetMapping("/excel")
     @GetMapping("/excel")
@@ -91,6 +96,13 @@ public class ProgrammeController extends BaseController {
         ExcelUtils.export(response, data);
         ExcelUtils.export(response, data);
     }
     }
 
 
+    @GetMapping("/excelGO")
+    @ResponseBody
+    public void excelGO(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<ProgrammeShowDTO> data = this.showAll(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+
     @GetMapping(value = "/excelTemp", produces = "application/vnd.ms-excel;charset=utf-8")
     @GetMapping(value = "/excelTemp", produces = "application/vnd.ms-excel;charset=utf-8")
     public void excelTemp(HttpServletResponse response) throws IOException {
     public void excelTemp(HttpServletResponse response) throws IOException {
 //        ExcelUtils.export1(response, ProgrammeDTO.class);
 //        ExcelUtils.export1(response, ProgrammeDTO.class);
@@ -98,13 +110,15 @@ public class ProgrammeController extends BaseController {
     }
     }
 
 
     @PostMapping("/upload")
     @PostMapping("/upload")
-    public void uploadFile(@RequestParam("file") MultipartFile file) {
-        try {
-            programmeService.upload(file, SecurityUtils.getAuthenticatedUser().getId());
-        } catch (IOException e) {
-            log.error("上传失败", e);
-            throw new BusinessException("上传失败", e.getMessage());
-        }
+    public void uploadFile(@RequestParam("file") MultipartFile file) throws Exception {
+        programmeService.upload(file, SecurityUtils.getAuthenticatedUser().getId());
+//        try {
+//            programmeService.upload(file, SecurityUtils.getAuthenticatedUser().getId());
+//        } catch (Exception e) {
+//            log.error("上传失败", e);
+////            throw new BusinessException("上传失败", e.getMessage());
+//            throw e;
+//        }
     }
     }
 
 
     @ApiOperation("移出分组")
     @ApiOperation("移出分组")
@@ -179,6 +193,14 @@ public class ProgrammeController extends BaseController {
         return programmeService.toShowDTO(programme);
         return programmeService.toShowDTO(programme);
     }
     }
 
 
+    @PostMapping("/showAll")
+    @ApiOperation("考级机构查看节目信息")
+    public Page<ProgrammeShowDTO> showAll(@RequestBody PageQuery pageQuery) {
+        Page<Programme> all = programmeService.all2(pageQuery);
+        return new PageImpl<>(programmeService.toShowDTOList(all.getContent()), all.getPageable()
+                , all.getTotalElements());
+    }
+
     @ApiOperation("获取手机号/token")
     @ApiOperation("获取手机号/token")
     @PostMapping("/getAuth")
     @PostMapping("/getAuth")
     public Map<String, String> getAuth(@RequestParam Long id, @RequestParam String phone) {
     public Map<String, String> getAuth(@RequestParam Long id, @RequestParam String phone) {

+ 3 - 6
src/main/resources/application.yaml

@@ -9,15 +9,12 @@ server:
         whitelabel:
         whitelabel:
             enabled: false
             enabled: false
     tomcat:
     tomcat:
-        max-http-form-post-size: 200MB
+        max-http-form-post-size: 400MB
 spring:
 spring:
     profiles:
     profiles:
         active: dev
         active: dev
     datasource:
     datasource:
         url: jdbc:mysql://mysql.izouma.com/exam?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
         url: jdbc:mysql://mysql.izouma.com/exam?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
-#        url: jdbc:mysql://localhost:3306/exam_test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
-#        username: root
-#        password: 123456
         username: microball
         username: microball
         password: 2wsx@WSX#EDC
         password: 2wsx@WSX#EDC
         hikari:
         hikari:
@@ -46,8 +43,8 @@ spring:
                 min_idle: 0
                 min_idle: 0
     servlet:
     servlet:
         multipart:
         multipart:
-            max_file_size: 200MB
-            max_request_size: 200MB
+            max_file_size: 400MB
+            max_request_size: 400MB
     freemarker:
     freemarker:
         settings:
         settings:
             number_format: 0
             number_format: 0

+ 1 - 0
src/main/resources/genjson/Announcement.json

@@ -0,0 +1 @@
+{"tableName":"Announcement","className":"Announcement","remark":"通知公告","genTable":true,"genClass":true,"genList":true,"genForm":true,"genRouter":true,"javaPath":"/Users/qiufangchao/Desktop/project/wenlvju/src/main/java/com/izouma/wenlvju","viewPath":"/Users/qiufangchao/Desktop/project/wenlvju/src/main/vue/src/views","routerPath":"/Users/qiufangchao/Desktop/project/wenlvju/src/main/vue/src","resourcesPath":"/Users/qiufangchao/Desktop/project/wenlvju/src/main/resources","dataBaseType":"Mysql","fields":[{"name":"title","modelName":"title","remark":"标题","showInList":true,"showInForm":true,"formType":"singleLineText"},{"name":"content","modelName":"content","remark":"内容","showInList":true,"showInForm":true,"formType":"richText"}],"readTable":false,"dataSourceCode":"dataSource","genJson":"","subtables":[],"update":false,"basePackage":"com.izouma.wenlvju","tablePackage":"com.izouma.wenlvju.domain.Announcement"}

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
src/main/resources/genjson/TrainingInstitution.json


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
src/main/resources/templates/RateTemplate.ftl


+ 1 - 0
src/main/vue/package.json

@@ -31,6 +31,7 @@
     "vue-avatar-cropper": "^1.0.5",
     "vue-avatar-cropper": "^1.0.5",
     "vue-axios": "^2.1.5",
     "vue-axios": "^2.1.5",
     "vue-chartjs": "^3.5.0",
     "vue-chartjs": "^3.5.0",
+    "vue-clipboard2": "^0.3.3",
     "vue-grid-layout": "^2.3.7",
     "vue-grid-layout": "^2.3.7",
     "vue-i18n": "^8.18.2",
     "vue-i18n": "^8.18.2",
     "vue-router": "^3.3.4",
     "vue-router": "^3.3.4",

+ 5 - 1
src/main/vue/src/components/OrganizationLog.vue

@@ -135,7 +135,11 @@
                             </el-form-item>
                             </el-form-item>
                             <el-form-item label="营业执照" prop="businessLicense" class="address">
                             <el-form-item label="营业执照" prop="businessLicense" class="address">
                                 <!-- <single-upload v-model="formData.businessLicense"></single-upload> -->
                                 <!-- <single-upload v-model="formData.businessLicense"></single-upload> -->
-                                <img style="width:100px;height100px" :src="formData.businessLicense" alt="" />
+                                <el-image
+                                    style="width:100px;height100px"
+                                    :src="formData.businessLicense"
+                                    :preview-src-list="[formData.businessLicense]"
+                                ></el-image>
                             </el-form-item>
                             </el-form-item>
                         </div>
                         </div>
                     </el-collapse-transition>
                     </el-collapse-transition>

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

@@ -83,6 +83,9 @@
                             <el-form-item prop="instructor" label="指导老师">
                             <el-form-item prop="instructor" label="指导老师">
                                 <el-input v-model="formData.instructor" class="width" readonly></el-input>
                                 <el-input v-model="formData.instructor" class="width" readonly></el-input>
                             </el-form-item>
                             </el-form-item>
+                            <el-form-item prop="instructorPhone" label="联系方式">
+                                <el-input v-model="formData.instructorPhone" class="width" readonly></el-input>
+                            </el-form-item>
                             <div
                             <div
                                 v-if="
                                 v-if="
                                     formData.specialty == '中国画' ||
                                     formData.specialty == '中国画' ||

+ 328 - 0
src/main/vue/src/components/ProgrammeLog1.vue

@@ -0,0 +1,328 @@
+<template>
+    <el-dialog
+        v-loading="saving"
+        @close="closeDialog"
+        title="节目详情"
+        center
+        :visible.sync="dialogVisible"
+        width="800px"
+    >
+        <div class="edit-view">
+            <el-form
+                :model="formData"
+                :rules="rules"
+                ref="form"
+                label-width="80px"
+                label-position="right"
+                size="small"
+                style="max-width: 700px;"
+            >
+                <el-timeline>
+                    <el-timeline-item placement="top" size="normal" timestamp="节目信息">
+                        <el-card shadow="hover" :body-style="{ padding: '20px' }">
+                            <el-form-item prop="name" label="节目名称">
+                                <el-input v-model="formData.name" class="width" readonly></el-input>
+                            </el-form-item>
+                            <el-form-item prop="specialtyId" label="参赛专业">
+                                <el-input v-model="formData.specialty" class="width" readonly></el-input>
+                            </el-form-item>
+                            <el-form-item prop="competitionGroup" label="参赛组别">
+                                <el-select
+                                    v-model="formData.competitionGroup"
+                                    class="width"
+                                    clearable
+                                    filterable
+                                    placeholder="请选择"
+                                    disabled
+                                >
+                                    <el-option
+                                        v-for="(item, index) in competitionGroupOptions"
+                                        :key="index"
+                                        :label="item.label"
+                                        :value="item.value"
+                                    >
+                                    </el-option>
+                                </el-select>
+                            </el-form-item>
+                            <el-form-item prop="levelSettingId" label="参赛级别" v-if="formData.competitionGroup">
+                                <el-input v-model="formData.level" class="width" readonly></el-input>
+                            </el-form-item>
+                            <el-form-item
+                                prop="durationOfWork"
+                                label="作品时长"
+                                v-if="
+                                    formData.specialtyId !== 187 &&
+                                        formData.specialtyId !== 188 &&
+                                        formData.specialtyId !== 189 &&
+                                        formData.specialtyId !== 190 &&
+                                        formData.specialtyId !== 191 &&
+                                        formData.specialtyId !== 192 &&
+                                        formData.specialtyId !== 193 &&
+                                        formData.specialtyId !== 194 &&
+                                        formData.specialtyId !== 589 &&
+                                        formData.specialtyId !== 590 &&
+                                        formData.specialtyId !== 591 &&
+                                        formData.specialtyId !== 592 &&
+                                        formData.specialtyId !== 593 &&
+                                        formData.specialtyId !== 594 &&
+                                        formData.specialtyId !== 595 &&
+                                        formData.specialtyId !== 596 &&
+                                        formData.specialtyId !== 597 &&
+                                        formData.specialtyId !== 598 &&
+                                        formData.specialtyId !== 599 &&
+                                        formData.specialtyId !== 600 &&
+                                        formData.specialtyId !== 601 &&
+                                        formData.specialtyId !== 602 &&
+                                        formData.specialtyId !== 603 &&
+                                        formData.specialtyId !== 604 &&
+                                        formData.specialtyId !== 605
+                                "
+                            >
+                                <el-input v-model="formData.durationOfWork" class="width" readonly></el-input>
+                            </el-form-item>
+                            <el-form-item prop="instructor" label="指导老师">
+                                <el-input v-model="formData.instructor" class="width" readonly></el-input>
+                            </el-form-item>
+                            <div
+                                v-if="
+                                    formData.specialty == '中国画' ||
+                                        formData.specialty == '美术' ||
+                                        formData.specialty == '西画' ||
+                                        formData.specialty == '书法' ||
+                                        formData.specialty == '漫画' ||
+                                        formData.specialty == '手工技艺' ||
+                                        formData.specialty == '摄影' ||
+                                        formData.specialty == '篆刻' ||
+                                        formData.specialty == '人物' ||
+                                        formData.specialty == '山水' ||
+                                        formData.specialty == '花鸟' ||
+                                        formData.specialty == '素描' ||
+                                        formData.specialty == '速写' ||
+                                        formData.specialty == '水粉画' ||
+                                        formData.specialty == '水彩画' ||
+                                        formData.specialty == '油画' ||
+                                        formData.specialty == '软笔书法' ||
+                                        formData.specialty == '硬笔书法' ||
+                                        formData.specialty == '剪纸' ||
+                                        formData.specialty == '泥塑' ||
+                                        formData.specialty == '年画' ||
+                                        formData.specialty == '皮影制作' ||
+                                        formData.specialty == '陶艺' ||
+                                        formData.specialty == '染织' ||
+                                        formData.specialty == '版画'
+                                "
+                            >
+                                <el-form-item prop="annex" v-if="formData.annex" label="作品图片">
+                                    <img class="imgBox" :src="formData.annex" alt="" />
+                                </el-form-item>
+                            </div>
+                            <div v-else>
+                                <el-form-item prop="video" label="作品视频" v-if="formData.video">
+                                    <video-upload v-model="videos" class="width" :readonly="true"></video-upload>
+                                </el-form-item>
+                            </div>
+                        </el-card>
+                    </el-timeline-item>
+                    <el-collapse-transition>
+                        <div v-show="showMore">
+                            <el-timeline-item placement="top" size="normal" timestamp="单位信息">
+                                <el-card shadow="hover" :body-style="{ padding: '20px' }">
+                                    <el-form-item prop="gradingOrganizationId" label="考级机构">
+                                        <el-input
+                                            v-model="formData.gradingOrganization"
+                                            class="width"
+                                            readonly
+                                        ></el-input>
+                                    </el-form-item>
+                                    <el-form-item prop="organizationId" label="承办单位">
+                                        <el-input v-model="formData.organization" class="width" readonly></el-input>
+                                    </el-form-item>
+                                    <el-form-item prop="examPoint" label="考级点">
+                                        <el-input v-model="formData.examPoint" class="width" readonly></el-input>
+                                    </el-form-item>
+                                    <el-form-item prop="contact" label="联系人">
+                                        <el-input v-model="formData.contact" class="width" readonly></el-input>
+                                    </el-form-item>
+                                    <el-form-item prop="phone" label="联系电话">
+                                        <el-input v-model="formData.phone" class="width" readonly></el-input>
+                                    </el-form-item>
+                                </el-card>
+                            </el-timeline-item>
+
+                            <el-timeline-item placement="top" size="normal" timestamp="参演人员">
+                                <el-card shadow="hover" :body-style="{ padding: '20px' }">
+                                    <el-table
+                                        :data="participants"
+                                        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"
+                                    >
+                                        <el-table-column prop="img" label="证件照">
+                                            <template slot-scope="{ row }">
+                                                <el-image
+                                                    style="width: 30px; height: 30px;"
+                                                    :src="row.img"
+                                                    fit="cover"
+                                                    :preview-src-list="[row.img]"
+                                                ></el-image>
+                                            </template>
+                                        </el-table-column>
+                                        <el-table-column prop="name" label="姓名" min-width="80"> </el-table-column>
+                                        <el-table-column prop="birthday" label="出生年月" min-width="100">
+                                        </el-table-column>
+                                        <el-table-column prop="sex" label="性别" min-width="70"> </el-table-column>
+                                        <el-table-column prop="phone" label="联系方式" min-width="100">
+                                        </el-table-column>
+                                        <el-table-column prop="certificate" label="考级证书">
+                                            <template slot-scope="{ row }">
+                                                <el-image
+                                                    style="width: 30px; height: 30px;"
+                                                    :src="row.certificate"
+                                                    fit="cover"
+                                                    :preview-src-list="[row.certificate]"
+                                                ></el-image>
+                                            </template>
+                                        </el-table-column>
+                                        <el-table-column prop="idNo" label="身份证号" min-width="100">
+                                        </el-table-column>
+                                    </el-table>
+                                </el-card>
+                            </el-timeline-item>
+                        </div>
+                    </el-collapse-transition>
+                    <div style="width:100%;textAlign:center">
+                        <el-button
+                            class="more"
+                            round
+                            type="primary"
+                            :plain="!showMore"
+                            :icon="showMore ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
+                            @click="showMore = !showMore"
+                        ></el-button>
+                    </div>
+                </el-timeline>
+                <!-- <el-form-item> </el-form-item> -->
+            </el-form>
+            <!-- <div class="btn">
+                <el-button @click="$router.go(-1)">返回</el-button>
+            </div> -->
+        </div>
+    </el-dialog>
+</template>
+<script>
+import delChild from '@/mixins/delChild';
+import { mapState } from 'vuex';
+export default {
+    name: 'ProgrammeShow',
+    mixins: [delChild],
+    props: ['dialogVisible'],
+    created() {},
+    data() {
+        return {
+            saving: false,
+            formData: {},
+            show: false,
+            showMore: false,
+            videos: {},
+            level: '',
+            rules: {
+                phone: [
+                    {
+                        pattern: /^1[3-9]\d{9}$/,
+                        message: '请输入正确的手机号',
+                        trigger: 'blur'
+                    }
+                ]
+            },
+            competitionGroupOptions: [
+                { label: '个人', value: 'SINGLE' },
+                { label: '集体', value: 'COLLECTIVE' }
+            ],
+            levelSingleOptions: [],
+            levelCollectiveOptions: [],
+            gradingOrganizationIdOptions: [],
+            organizationIdOptions: [],
+            artTypes: [],
+            optionProps: {
+                value: 'id',
+                label: 'name',
+                children: 'children',
+                multiple: false,
+                emitPath: false,
+                checkStrictly: true,
+                expandTrigger: 'hover'
+            },
+            participants: [],
+            programmeId: ''
+        };
+    },
+    methods: {
+        dataApi(id) {
+            if (id) {
+                this.$http
+                    .get('programme/getShow/' + id)
+                    .then(res => {
+                        this.formData = res;
+                        this.participants = res.participants;
+                        // console.log(res);
+                        this.videos = {
+                            src: res.video
+                        };
+                    })
+                    .catch(e => {
+                        console.log(e);
+                        this.$message.error(e.error);
+                    });
+            }
+        },
+        closeDialog() {
+            this.$emit('close');
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.edit-view {
+    padding: 0 0;
+    background-color: transparent;
+}
+.width {
+    width: 260px;
+}
+// /deep/ .el-timeline-item {
+//     padding-bottom: 35px;
+// }
+.imgBox {
+    width: 178px;
+    height: 178px;
+    border-radius: 4px;
+}
+.btn {
+    position: fixed;
+    bottom: 0;
+    width: 100%;
+    background: #ffffff;
+    height: 50px;
+    line-height: 50px;
+    z-index: 999;
+    margin-left: -20px;
+    padding-left: 20px;
+}
+/deep/.el-input.is-disabled .el-input__inner {
+    background-color: #ffffff;
+    color: #606266;
+}
+/deep/.el-timeline-item__timestamp {
+    color: #0561d9;
+    line-height: 1;
+    font-size: 14px;
+}
+/deep/.el-timeline-item__node {
+    background-color: #5b9bed;
+}
+/deep/.el-timeline-item__tail {
+    border-left: 2px solid #7cace9;
+}
+</style>

+ 6 - 3
src/main/vue/src/components/RichText.vue

@@ -42,14 +42,17 @@ export default {
                 menubar: false,
                 menubar: false,
                 branding: false,
                 branding: false,
                 statusbar: false,
                 statusbar: false,
-                height: 400,
+                height: 600,
+                width: 700,
                 toolbar:
                 toolbar:
-                    'undo redo | styleselect bold italic strikethrough forecolor backcolor  | image media link blockquote visualblocks insert | formatselect | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | preview fullscreen code help',
+                    'undo redo  | indent2em bold italic strikethrough forecolor backcolor fontsizeselect lineheight | image media link blockquote visualblocks insert  | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | preview fullscreen code help',
                 plugins: [
                 plugins: [
-                    'advlist autolink lists link image charmap print preview anchor textcolor',
+                    'advlist autolink indent2em lists link image charmap print preview anchor textcolor',
                     'searchreplace visualblocks code fullscreen',
                     'searchreplace visualblocks code fullscreen',
                     'insertdatetime media table contextmenu paste code help imagetools'
                     'insertdatetime media table contextmenu paste code help imagetools'
                 ],
                 ],
+                lineheight_formats: '1 1.1 1.2 1.3 1.4 1.5 2',
+                fontsize_formats: '8px 10px 12px 14px 16px 18px 24px 36px 48px',
                 images_upload_url: this.$baseUrl + '/upload/file',
                 images_upload_url: this.$baseUrl + '/upload/file',
                 images_upload_handler: (blobInfo, success, failure) => {
                 images_upload_handler: (blobInfo, success, failure) => {
                     let formData = new FormData();
                     let formData = new FormData();

+ 2 - 0
src/main/vue/src/main.js

@@ -18,6 +18,7 @@ import DistrictSelect from '@/components/DistrictSelect';
 import Formatters from '@/mixins/formatters';
 import Formatters from '@/mixins/formatters';
 import 'normalize.css/normalize.css';
 import 'normalize.css/normalize.css';
 import 'element-ui/lib/theme-chalk/index.css';
 import 'element-ui/lib/theme-chalk/index.css';
+import VueClipboard from 'vue-clipboard2';
 // 修改 el-dialog 默认点击遮照为不关闭
 // 修改 el-dialog 默认点击遮照为不关闭
 ElementUI.Dialog.props.closeOnClickModal.default = false;
 ElementUI.Dialog.props.closeOnClickModal.default = false;
 
 
@@ -46,6 +47,7 @@ Vue.config.productionTip = false;
 Vue.use(ElementUI, { size: 'small' });
 Vue.use(ElementUI, { size: 'small' });
 Vue.use(http);
 Vue.use(http);
 Vue.use(dataExport);
 Vue.use(dataExport);
+Vue.use(VueClipboard);
 Vue.component('sortable-header', SortableHeader);
 Vue.component('sortable-header', SortableHeader);
 Vue.component('multi-upload', MultiUpload);
 Vue.component('multi-upload', MultiUpload);
 Vue.component('single-upload', SingleUpload);
 Vue.component('single-upload', SingleUpload);

+ 1 - 0
src/main/vue/src/mixins/pageableTable.js

@@ -154,6 +154,7 @@ export default {
                 })
                 })
                 .catch(_ => {});
                 .catch(_ => {});
             this.sortStr = sortStr;
             this.sortStr = sortStr;
+            console.log(this.sortStr);
             this.getData();
             this.getData();
         }
         }
     }
     }

+ 53 - 1
src/main/vue/src/router.js

@@ -781,6 +781,49 @@ const router = new Router({
                     meta: {
                     meta: {
                         title: '节目评审'
                         title: '节目评审'
                     }
                     }
+                },
+                {
+                    path: '/trainingInstitutionEdit',
+                    name: 'TrainingInstitutionEdit',
+                    component: () =>
+                        import(/* webpackChunkName: "trainingInstitutionEdit" */ '@/views/TrainingInstitutionEdit.vue'),
+                    meta: {
+                        title: '培训机构编辑'
+                    }
+                },
+                {
+                    path: '/trainingInstitutionList',
+                    name: 'TrainingInstitutionList',
+                    component: () =>
+                        import(/* webpackChunkName: "trainingInstitutionList" */ '@/views/TrainingInstitutionList.vue'),
+                    meta: {
+                        title: '培训机构'
+                    }
+                },
+                {
+                    path: '/announcementEdit',
+                    name: 'AnnouncementEdit',
+                    component: () => import(/* webpackChunkName: "announcementEdit" */ '@/views/AnnouncementEdit.vue'),
+                    meta: {
+                        title: '通知公告编辑'
+                    }
+                },
+                {
+                    path: '/announcementDetail',
+                    name: 'AnnouncementDetail',
+                    component: () =>
+                        import(/* webpackChunkName: "announcementEdit" */ '@/views/AnnouncementDetail.vue'),
+                    meta: {
+                        title: '通知公告'
+                    }
+                },
+                {
+                    path: '/announcementList',
+                    name: 'AnnouncementList',
+                    component: () => import(/* webpackChunkName: "announcementList" */ '@/views/AnnouncementList.vue'),
+                    meta: {
+                        title: '通知公告'
+                    }
                 }
                 }
                 /**INSERT_LOCATION**/
                 /**INSERT_LOCATION**/
             ]
             ]
@@ -792,6 +835,15 @@ const router = new Router({
             meta: {
             meta: {
                 title: '登录'
                 title: '登录'
             }
             }
+        },
+        /**初审 */
+        {
+            path: '/programmeGOList',
+            name: 'ProgrammegoList',
+            component: () => import(/* webpackChunkName: "programmeList" */ '@/views/performance/ProgrammeGOList.vue'),
+            meta: {
+                title: '节目列表'
+            }
         }
         }
     ]
     ]
 });
 });
@@ -815,7 +867,7 @@ router.beforeEach((to, from, next) => {
         return;
         return;
     }
     }
     // console.log(store.state.isORGANIZER);
     // console.log(store.state.isORGANIZER);
-    if (!store.state.userInfo && to.path !== '/login') {
+    if (!store.state.userInfo && to.path !== '/login' && to.path !== '/programmeGOList') {
         store
         store
             .dispatch('getUserInfo')
             .dispatch('getUserInfo')
             .then(() => {
             .then(() => {

+ 94 - 0
src/main/vue/src/views/AnnouncementDetail.vue

@@ -0,0 +1,94 @@
+<template>
+    <div class="edit-view">
+        <div class="title">{{ formData.title }}</div>
+        <div class="time">发布时间:{{ formData.createdAt }}</div>
+        <div class="content" v-html="formData.content"></div>
+    </div>
+</template>
+<script>
+export default {
+    name: 'AnnouncementEdit',
+    created() {
+        if (this.$route.query.id) {
+            this.$http
+                .get('announcement/get/' + this.$route.query.id)
+                .then(res => {
+                    this.formData = res;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.$message.error(e.error);
+                });
+        }
+    },
+    data() {
+        return {
+            saving: false,
+            formData: {},
+            rules: {}
+        };
+    },
+    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('/announcement/save', data, { body: 'json' })
+                .then(res => {
+                    this.saving = false;
+                    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(() => {
+                    return this.$http.post(`/announcement/del/${this.formData.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.$router.go(-1);
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        console.log(e);
+                        this.$message.error((e || {}).error || '删除失败');
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.title {
+    font-size: 24px;
+    text-align: center;
+    padding: 20px;
+    font-weight: bold;
+}
+.time {
+    font-size: 12px;
+    text-align: right;
+    margin-right: 50px;
+    padding: 10px;
+}
+
+.content {
+    padding: 20px 50px;
+}
+</style>

+ 106 - 0
src/main/vue/src/views/AnnouncementEdit.vue

@@ -0,0 +1,106 @@
+<template>
+    <div class="edit-view">
+        <el-form
+            :model="formData"
+            :rules="rules"
+            ref="form"
+            label-width="52px"
+            label-position="right"
+            size="small"
+            style="max-width: 700px;"
+        >
+            <el-form-item prop="title" label="标题">
+                <el-input v-model="formData.title"></el-input>
+            </el-form-item>
+            <el-form-item prop="type" label="类型">
+                <el-radio-group v-model="formData.type">
+                    <el-radio v-for="item in typeOptions" :key="item.value" :label="item.value">{{
+                        item.label
+                    }}</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item prop="content" label="内容">
+                <rich-text v-model="formData.content"></rich-text>
+            </el-form-item>
+            <el-form-item>
+                <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
+                <el-button @click="onDelete" :loading="saving" type="danger" v-if="formData.id">删除 </el-button>
+                <el-button @click="$router.go(-1)">取消</el-button>
+            </el-form-item>
+        </el-form>
+    </div>
+</template>
+<script>
+export default {
+    name: 'AnnouncementEdit',
+    created() {
+        if (this.$route.query.id) {
+            this.$http
+                .get('announcement/get/' + this.$route.query.id)
+                .then(res => {
+                    this.formData = res;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.$message.error(e.error);
+                });
+        }
+    },
+    data() {
+        return {
+            saving: false,
+            formData: {},
+            rules: {},
+            typeOptions: [
+                { label: '通知公告', value: 'NOTIFICATION' },
+                { label: '政策文件', value: 'POLICY' }
+            ]
+        };
+    },
+    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('/announcement/save', data, { body: 'json' })
+                .then(res => {
+                    this.saving = false;
+                    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(() => {
+                    return this.$http.post(`/announcement/del/${this.formData.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.$router.go(-1);
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        console.log(e);
+                        this.$message.error((e || {}).error || '删除失败');
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 169 - 0
src/main/vue/src/views/AnnouncementList.vue

@@ -0,0 +1,169 @@
+<template>
+    <div class="list-view">
+        <div class="filters-container">
+            <el-input placeholder="输入关键字" v-model="search" clearable class="filter-item"></el-input>
+            <el-button @click="getData" type="primary" icon="el-icon-search" class="filter-item">搜索 </el-button>
+            <el-button @click="addRow" type="primary" icon="el-icon-plus" class="filter-item">添加 </el-button>
+            <el-button
+                @click="download"
+                type="primary"
+                icon="el-icon-download"
+                :loading="downloading"
+                class="filter-item"
+                >导出EXCEL
+            </el-button>
+        </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="ID" width="100"> </el-table-column>
+            <el-table-column prop="title" label="标题"> </el-table-column>
+            <el-table-column prop="type" label="类型" :formatter="typeFormatter"> </el-table-column>
+            <el-table-column prop="content" label="内容"> </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" min-width="150">
+                <template slot-scope="{ row }">
+                    <el-button @click="editRow(row)" type="primary" size="mini" plain>编辑</el-button>
+                    <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</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>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+
+export default {
+    name: 'AnnouncementList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/announcement/all',
+            downloading: false,
+            typeOptions: [
+                { label: '通知公告', value: 'NOTIFICATION' },
+                { label: '政策文件', value: 'POLICY' }
+            ]
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        typeFormatter(row, column, cellValue, index) {
+            let selectedOption = this.typeOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        beforeGetData() {
+            return { search: this.search };
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/announcementEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/announcementEdit',
+                query: {
+                    id: row.id
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/announcement/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(`/announcement/del/${row.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 12 - 6
src/main/vue/src/views/Dashboard.vue

@@ -33,6 +33,8 @@
 <script>
 <script>
 import { GridLayout, GridItem } from 'vue-grid-layout';
 import { GridLayout, GridItem } from 'vue-grid-layout';
 import UserWidget from '../widgets/UserWidget';
 import UserWidget from '../widgets/UserWidget';
+import BoardWidget from '../widgets/BoardWidget.vue';
+import PolicyWidget from '../widgets/PolicyWidget.vue';
 import UserWidget2 from '../widgets/UserWidget2';
 import UserWidget2 from '../widgets/UserWidget2';
 import LineChartWidget from '../widgets/LineChartWidget';
 import LineChartWidget from '../widgets/LineChartWidget';
 import BarChartWidget from '../widgets/BarChartWidget';
 import BarChartWidget from '../widgets/BarChartWidget';
@@ -43,11 +45,13 @@ export default {
     data() {
     data() {
         return {
         return {
             layout: [
             layout: [
-                { x: 0, y: 0, w: 6, h: 4, i: '0', name: 'UserWidget' },
-                { x: 6, y: 0, w: 6, h: 4, i: '1', name: 'UserWidget2' },
-                { x: 0, y: 4, w: 6, h: 6, i: '2', name: 'BarChartWidget' },
-                { x: 0, y: 10, w: 6, h: 6, i: '3', name: 'LineChartWidget' },
-                { x: 6, y: 4, w: 6, h: 12, i: '4', name: 'PieChartWidget' }
+                { x: 0, y: 0, w: 12, h: 6, i: '0', name: 'BoardWidget' },
+                { x: 6, y: 0, w: 12, h: 6, i: '1', name: 'PolicyWidget' }
+                // { x: 0, y: 0, w: 6, h: 4, i: '2', name: 'UserWidget' },
+                // { x: 6, y: 4, w: 6, h: 4, i: '3', name: 'UserWidget2' },
+                // { x: 0, y: 8, w: 6, h: 6, i: '4', name: 'BarChartWidget' },
+                // { x: 0, y: 10, w: 6, h: 6, i: '5', name: 'LineChartWidget' },
+                // { x: 6, y: 8, w: 6, h: 12, i: '6', name: 'PieChartWidget' }
             ],
             ],
             editable: false
             editable: false
         };
         };
@@ -65,7 +69,9 @@ export default {
         UserWidget2,
         UserWidget2,
         LineChartWidget,
         LineChartWidget,
         BarChartWidget,
         BarChartWidget,
-        PieChartWidget
+        PieChartWidget,
+        BoardWidget,
+        PolicyWidget
     }
     }
 };
 };
 </script>
 </script>

+ 26 - 13
src/main/vue/src/views/Login.vue

@@ -499,25 +499,38 @@ export default {
             this.$refs.registerForm.validate(valid => {
             this.$refs.registerForm.validate(valid => {
                 if (valid) {
                 if (valid) {
                     this.loading = true;
                     this.loading = true;
+
                     this.$http
                     this.$http
-                        .post(
-                            '/user/regOrganization',
-                            // {
-                            // username: this.registerInfo.username,
-                            // password: this.registerInfo.password
-                            // },
-                            this.registerInfo,
-                            { body: 'json' }
-                        )
+                        .get('/organization/byName', { name: this.registerInfo.organizationName }, { body: 'json' })
                         .then(res => {
                         .then(res => {
-                            this.loading = false;
-                            this.$message.success('注册成功');
-                            this.register = false;
+                            if (res != null || res != 'undefind') {
+                                this.$confirm('该承办单位已有人注册,注册手机号为' + res + ',是否继续注册', '提示', {
+                                    confirmButtonText: '继续注册',
+                                    cancelButtonText: '返回登录',
+                                    type: 'warning'
+                                })
+                                    .then(() => {
+                                        this.$http
+                                            .post('/user/regOrganization', this.registerInfo, { body: 'json' })
+                                            .then(res => {
+                                                this.loading = false;
+                                                this.$message.success('注册成功');
+                                                this.register = false;
+                                            })
+                                            .catch(e => {
+                                                console.log(e);
+                                                this.loading = false;
+                                            });
+                                    })
+                                    .catch(() => {
+                                        this.loading = false;
+                                        this.register = false;
+                                    });
+                            }
                         })
                         })
                         .catch(e => {
                         .catch(e => {
                             console.log(e);
                             console.log(e);
                             this.loading = false;
                             this.loading = false;
-                            this.$message.error(e.error);
                         });
                         });
                 }
                 }
             });
             });

+ 180 - 0
src/main/vue/src/views/TrainingInstitutionEdit.vue

@@ -0,0 +1,180 @@
+<template>
+    <div class="edit-view">
+        <el-form
+            :model="formData"
+            :rules="rules"
+            ref="form"
+            label-width="178px"
+            label-position="right"
+            size="small"
+            style="max-width: 700px;"
+        >
+            <el-form-item prop="name" label="企业名称">
+                <el-input v-model="formData.name"></el-input>
+            </el-form-item>
+            <el-form-item prop="uscc" label="注册号">
+                <el-input v-model="formData.uscc"></el-input>
+            </el-form-item>
+            <el-form-item prop="businessScope" label="经营范围">
+                <el-input type="textarea" v-model="formData.businessScope"></el-input>
+            </el-form-item>
+            <el-form-item prop="address" label="企业住所">
+                <el-input v-model="formData.address"></el-input>
+            </el-form-item>
+            <el-form-item prop="businessPremise" label="生产经营场所">
+                <el-input v-model="formData.businessPremise"></el-input>
+            </el-form-item>
+            <el-form-item prop="privacyPolicy" label="法人姓名">
+                <el-input v-model="formData.privacyPolicy"></el-input>
+            </el-form-item>
+            <el-form-item prop="phone" label="短信号码">
+                <el-input v-model="formData.phone"></el-input>
+            </el-form-item>
+            <el-form-item prop="contactPhone" label="企业联系方式">
+                <el-input v-model="formData.contactPhone"></el-input>
+            </el-form-item>
+            <el-form-item prop="district" label="所属管区">
+                <el-input v-model="formData.district"></el-input>
+            </el-form-item>
+            <el-form-item prop="registeredCapital" label="注册资本(万)">
+                <el-input-number type="number" v-model="formData.registeredCapital"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="category" label="单位性质">
+                <el-input v-model="formData.category"></el-input>
+            </el-form-item>
+            <el-form-item prop="specialty" label="专业种类">
+                <el-input v-model="formData.specialty"></el-input>
+            </el-form-item>
+            <el-form-item prop="trainingSite" label="培训点数量三楼及以下">
+                <el-input-number type="number" v-model="formData.trainingSite"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="trainingSiteFour" label="培训点数量四楼及以上">
+                <el-input-number type="number" v-model="formData.trainingSiteFour"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="area" label="总面积">
+                <el-input v-model="formData.area"></el-input>
+            </el-form-item>
+            <el-form-item prop="classroomNum" label="教室数量">
+                <el-input-number type="number" v-model="formData.classroomNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="teacherNum" label="教师总数">
+                <el-input-number type="number" v-model="formData.teacherNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="fullTimeNum" label="专职数量">
+                <el-input-number type="number" v-model="formData.fullTimeNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="partTimeNum" label="兼职数量">
+                <el-input-number type="number" v-model="formData.partTimeNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="musicNum" label="音乐类">
+                <el-input-number type="number" v-model="formData.musicNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="danceNum" label="舞蹈类">
+                <el-input-number type="number" v-model="formData.danceNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="artNum" label="美术类">
+                <el-input-number type="number" v-model="formData.artNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="theatreOperaNum" label="戏剧戏曲">
+                <el-input-number type="number" v-model="formData.theatreOperaNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="folkMusicNum" label="曲艺类">
+                <el-input-number type="number" v-model="formData.folkMusicNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="qualificationNum" label="有教师资格证">
+                <el-input-number type="number" v-model="formData.qualificationNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="traineesPerYearNum" label="年培训人数">
+                <el-input-number type="number" v-model="formData.traineesPerYearNum"></el-input-number>
+            </el-form-item>
+            <el-form-item prop="examPoint" label="是否是艺术水平考级考点">
+                <!-- <el-input v-model="formData.examPoint"></el-input> -->
+                <el-radio-group v-model="formData.examPoint">
+                    <el-radio :label="true">是</el-radio>
+                    <el-radio :label="false">否</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item prop="gradingOrganization" label="艺术水平考级机构名称">
+                <el-input v-model="formData.gradingOrganization"></el-input>
+            </el-form-item>
+            <el-form-item prop="remark" label="备注">
+                <el-input v-model="formData.remark"></el-input>
+            </el-form-item>
+            <el-form-item>
+                <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
+                <el-button @click="onDelete" :loading="saving" type="danger" v-if="formData.id">删除 </el-button>
+                <el-button @click="$router.go(-1)">取消</el-button>
+            </el-form-item>
+        </el-form>
+    </div>
+</template>
+<script>
+export default {
+    name: 'TrainingInstitutionEdit',
+    created() {
+        if (this.$route.query.id) {
+            this.$http
+                .get('trainingInstitution/get/' + this.$route.query.id)
+                .then(res => {
+                    this.formData = res;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.$message.error(e.error);
+                });
+        }
+    },
+    data() {
+        return {
+            saving: false,
+            formData: {},
+            rules: {}
+        };
+    },
+    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('/trainingInstitution/save', data, { body: 'json' })
+                .then(res => {
+                    this.saving = false;
+                    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(() => {
+                    return this.$http.post(`/trainingInstitution/del/${this.formData.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.$router.go(-1);
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        console.log(e);
+                        this.$message.error((e || {}).error || '删除失败');
+                    }
+                });
+        }
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 279 - 0
src/main/vue/src/views/TrainingInstitutionList.vue

@@ -0,0 +1,279 @@
+<template>
+    <div class="list-view">
+        <div class="filters-container">
+            <el-input placeholder="输入关键字" v-model="search" clearable class="filter-item"></el-input>
+            <el-button @click="getData" type="primary" icon="el-icon-search" class="filter-item">搜索 </el-button>
+            <!-- <el-button @click="addRow" type="primary" icon="el-icon-plus" class="filter-item">添加 </el-button> -->
+            <el-button @click="download" type="primary" icon="el-icon-download" :loading="downloading"
+                >导出所有
+            </el-button>
+            <el-button @click="downloadTel" type="primary" icon="el-icon-download" :loading="downloading"
+                >导出固定电话
+            </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-button @click="sendSms" type="primary">短信通知 </el-button>
+        </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="ID" width="80"> </el-table-column>
+            <el-table-column prop="name" label="企业名称"> </el-table-column>
+            <el-table-column prop="uscc" label="注册号"> </el-table-column>
+            <el-table-column prop="businessScope" label="经营范围"> </el-table-column>
+            <el-table-column prop="address" label="企业住所"> </el-table-column>
+            <el-table-column prop="businessPremise" label="生产经营场所"> </el-table-column>
+            <el-table-column prop="privacyPolicy" label="法人姓名"> </el-table-column>
+            <el-table-column prop="phone" label="短信号码"> </el-table-column>
+            <el-table-column prop="contactPhone" label="企业联系方式"> </el-table-column>
+            <el-table-column prop="district" label="所属管区"> </el-table-column>
+            <el-table-column prop="registeredCapital" label="注册资本(万)"> </el-table-column>
+            <el-table-column prop="engagedInTraining" label="是否从事文化艺术类校外培训"> </el-table-column>
+            <el-table-column prop="category" label="单位性质"> </el-table-column>
+            <el-table-column prop="specialty" label="专业种类"> </el-table-column>
+            <el-table-column prop="trainingSite" label="培训点数量三楼及以下"> </el-table-column>
+            <el-table-column prop="trainingSiteFour" label="培训点数量四楼及以上"> </el-table-column>
+            <el-table-column prop="area" label="总面积"> </el-table-column>
+            <el-table-column prop="classroomNum" label="教室数量"> </el-table-column>
+            <el-table-column prop="teacherNum" label="教师总数"> </el-table-column>
+            <el-table-column prop="fullTimeNum" label="专职数量"> </el-table-column>
+            <el-table-column prop="partTimeNum" label="兼职数量"> </el-table-column>
+            <el-table-column prop="musicNum" label="音乐类"> </el-table-column>
+            <el-table-column prop="danceNum" label="舞蹈类"> </el-table-column>
+            <el-table-column prop="artNum" label="美术类"> </el-table-column>
+            <el-table-column prop="theatreOperaNum" label="戏剧戏曲"> </el-table-column>
+            <el-table-column prop="folkMusicNum" label="曲艺类"> </el-table-column>
+            <el-table-column prop="qualificationNum" label="有教师资格证"> </el-table-column>
+            <el-table-column prop="traineesPerYearNum" label="年培训人数"> </el-table-column>
+            <el-table-column prop="examPoint" label="是否是艺术水平考级考点"> </el-table-column>
+            <el-table-column prop="gradingOrganization" label="艺术水平考级机构名称"> </el-table-column>
+            <el-table-column prop="remark" label="备注"> </el-table-column>
+            <el-table-column label="操作" align="center" fixed="right" min-width="150">
+                <template slot-scope="{ row }">
+                    <el-button @click="editRow(row)" type="primary" size="mini" plain>编辑</el-button>
+                    <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</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>
+    </div>
+</template>
+<script>
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+import resolveUrl from 'resolve-url';
+
+export default {
+    name: 'TrainingInstitutionList',
+    mixins: [pageableTable],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/trainingInstitution/all',
+            downloading: false,
+            loading: false,
+            uploadUrl: ''
+        };
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        },
+        headers() {
+            return {
+                Authorization: 'Bearer ' + sessionStorage.getItem('token')
+            };
+        }
+    },
+    created() {
+        this.uploadUrl = resolveUrl(this.$baseUrl, 'trainingInstitution/upload');
+    },
+    methods: {
+        beforeGetData() {
+            return {
+                search: this.search,
+                sort: 'firstWrite,desc'
+            };
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/trainingInstitutionEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        editRow(row) {
+            this.$router.push({
+                path: '/trainingInstitutionEdit',
+                query: {
+                    id: row.id
+                }
+            });
+        },
+        download() {
+            this.downloading = true;
+            this.$axios
+                .get('/trainingInstitution/excel', {
+                    responseType: 'blob',
+                    params: { size: 100000 }
+                })
+                .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);
+                });
+        },
+        downloadTel() {
+            this.downloading = true;
+            this.$axios
+                .get('/trainingInstitution/excel1', {
+                    responseType: 'blob',
+                    params: { size: 50000 }
+                })
+                .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(`/trainingInstitution/del/${row.id}`);
+                })
+                .then(() => {
+                    this.$message.success('删除成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        },
+        sendSms() {
+            this.$alert('确认发送短信吗?', '提示')
+                .then(() => {
+                    return this.$http.get(`/trainingInstitution/batchSend`);
+                })
+                .then(() => {
+                    this.$message.success('发送成功');
+                    // this.getData();
+                })
+                .catch(e => {
+                    if (e !== 'cancel') {
+                        this.$message.error(e.error);
+                    }
+                });
+        },
+        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;
+            });
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.uploader {
+    display: inline-block;
+    margin: 0 10px;
+}
+</style>

+ 1 - 0
src/main/vue/src/views/performance/ArrangeJudgeList.vue

@@ -72,6 +72,7 @@
                             :plain="!showMore"
                             :plain="!showMore"
                             :icon="showMore ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
                             :icon="showMore ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
                             @click="showMore = !showMore"
                             @click="showMore = !showMore"
+                            size="mini"
                             >{{ showMore ? '隐藏查询区域' : '显示查询区域' }}</el-button
                             >{{ showMore ? '隐藏查询区域' : '显示查询区域' }}</el-button
                         >
                         >
                     </div>
                     </div>

+ 3 - 1
src/main/vue/src/views/performance/PerformanceEdit.vue

@@ -120,7 +120,9 @@
             <el-form-item prop="codeImg" label="活动工作群">
             <el-form-item prop="codeImg" label="活动工作群">
                 <single-upload v-model="formData.codeImg"></single-upload>
                 <single-upload v-model="formData.codeImg"></single-upload>
             </el-form-item>
             </el-form-item>
-            <!-- <el-form-item> </el-form-item> -->
+            <el-form-item prop="close" label="开启">
+                <el-switch v-model="formData.close"></el-switch>
+            </el-form-item>
         </el-form>
         </el-form>
         <div class="btn">
         <div class="btn">
             <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
             <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>

+ 13 - 4
src/main/vue/src/views/performance/ProgrammeEdit.vue

@@ -540,7 +540,8 @@ export default {
                 .map(item => {
                 .map(item => {
                     return {
                     return {
                         ...item,
                         ...item,
-                        programmeId: this.programmeId
+                        programmeId: this.programmeId,
+                        performanceId: this.formData.performanceId
                     };
                     };
                 });
                 });
 
 
@@ -587,10 +588,18 @@ export default {
 
 
                     this.programmeId = res.id;
                     this.programmeId = res.id;
                     this.$nextTick(() => {
                     this.$nextTick(() => {
-                        this.$http.post('/participant/batchSave', this.saveOtherJson, { body: 'json' });
+                        this.$http
+                            .post('/participant/batchSave', this.saveOtherJson, { body: 'json' })
+                            .then(() => {
+                                this.$message.success('成功');
+                                this.$router.go(-1);
+                            })
+                            .catch(e => {
+                                console.log(e);
+                                this.saving = false;
+                                this.$message.error(e.error);
+                            });
                     });
                     });
-                    this.$message.success('成功');
-                    this.$router.go(-1);
                 })
                 })
                 .catch(e => {
                 .catch(e => {
                     console.log(e);
                     console.log(e);

+ 388 - 0
src/main/vue/src/views/performance/ProgrammeGOList.vue

@@ -0,0 +1,388 @@
+<template>
+    <div class="list-view">
+        <div class="filters-container">
+            <el-form :model="form" inline size="mini" label-width="100px">
+                <el-form-item>
+                    <!-- <el-button @click="getData" type="primary" icon="el-icon-search">查询 </el-button>
+                    <el-button @click="clearSearch" type="primary">清空 </el-button> -->
+                    <!-- <el-button @click="addRow" type="primary" icon="el-icon-plus">添加 </el-button> -->
+                    <el-button
+                        @click="download"
+                        type="primary"
+                        icon="el-icon-download"
+                        :loading="downloading"
+                        :disabled="totalElements < 1"
+                        >导出
+                    </el-button>
+                </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="id" label="节目编号" width="80" fixed="left"> </el-table-column>
+            <el-table-column prop="name" label="节目名称" fixed="left"> </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="contact" label="联系人" min-width="68"> </el-table-column>
+            <el-table-column prop="gradingOrganizationId" label="考级机构" show-overflow-tooltip min-width="160">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+                <template slot-scope="{ row }">
+                    <span>{{ row.gradingOrganization }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="organizationId" label="承办单位" min-width="160">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+                <template slot-scope="{ row }">
+                    <span>{{ row.organization }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="examPoint" label="考级点" min-width="160">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+            </el-table-column>
+            <el-table-column
+                prop="programmeStatus"
+                label="节目状态"
+                min-width="100"
+                :formatter="programmeStatusFormatter"
+            ></el-table-column>
+            <el-table-column label="操作" align="left" fixed="right" min-width="180">
+                <template slot-scope="{ row, $index }">
+                    <el-button @click="showRow(row)" size="mini" plain>查看</el-button>
+                    <el-button type="warning" @click="playVideo(row, $index)" 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
+            :title="programme.name"
+            class="videoDialog"
+            destroy-on-close
+            center
+            append-to-body
+            :visible.sync="showViedo"
+            width="auto"
+        >
+            <video
+                :src="programme.video"
+                controls
+                style="max-height: 600px; max-width: 100%; margin: 0 auto"
+                v-if="programme.video"
+            >
+                您的浏览器不支持 video 标签。
+            </video>
+            <img
+                style="max-height: 600px; max-width: 100%; display: block; margin: auto"
+                :src="programme.annex"
+                alt=""
+                v-if="programme.annex"
+            />
+            <div style="display: block; margin: 10px;">
+                <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-button @click="showViedo = false" size="mini">关闭</el-button>
+            </div>
+        </el-dialog>
+        <programme-log :dialogVisible="isShow" @close="isShow = false" ref="public"></programme-log>
+    </div>
+</template>
+<script>
+import delChild from '@/mixins/delChild';
+import { mapState } from 'vuex';
+import pageableTable from '@/mixins/pageableTable';
+import ProgrammeLog from '@/components/ProgrammeLog1.vue';
+export default {
+    name: 'ProgrammeList',
+    mixins: [pageableTable, delChild],
+    data() {
+        return {
+            multipleMode: false,
+            search: '',
+            url: '/programme/showAll',
+            downloading: false,
+            competitionGroupOptions: [
+                { label: '个人', value: 'SINGLE' },
+                { label: '集体', value: 'COLLECTIVE' }
+            ],
+            form: {},
+            levelSingleOptions: [],
+            levelCollectiveOptions: [],
+            dialogUrl: '',
+            dialogCode: false,
+            isShow: false,
+            gradingOrganizationIdOptions: [],
+            organizationIdOptions: [],
+            performanceId: '',
+            performances: [],
+            performance: {},
+            artTypes: [],
+            optionProps: {
+                value: 'id',
+                label: 'name',
+                children: 'children',
+                multiple: false,
+                emitPath: false,
+                checkStrictly: true,
+                expandTrigger: 'hover'
+            },
+            showViedo: false,
+            showImg: false,
+            videoUrl: '',
+            annex: '',
+            programmeStatusOptions: [
+                { label: '未提交', value: 'INITIAL' },
+                { label: '已提交', value: 'SUBMIT' },
+                { label: '初选未通过', value: 'AUDIT_FAILED' },
+                { label: '审核未通过', value: 'REVIEW_FAILED' }
+            ],
+            showMore: false,
+            programme: {},
+            index: 0
+        };
+    },
+    created() {},
+    components: {
+        ProgrammeLog
+    },
+    computed: {
+        selection() {
+            return this.$refs.table.selection.map(i => i.id);
+        }
+    },
+    methods: {
+        programmeStatusFormatter(row, column, cellValue, index) {
+            let selectedOption = this.programmeStatusOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        competitionGroupFormatter(row, column, cellValue, index) {
+            let selectedOption = this.competitionGroupOptions.find(i => i.value === cellValue);
+            if (selectedOption) {
+                return selectedOption.label;
+            }
+            return '';
+        },
+        beforeGetData() {
+            let data = {
+                query: {}
+            };
+            if (this.$route.query.gid) {
+                data.query.gradingOrganizationId = this.$route.query.gid;
+            } else {
+                data.query.gradingOrganizationId = 0;
+            }
+            return data;
+        },
+        toggleMultipleMode(multipleMode) {
+            this.multipleMode = multipleMode;
+            if (!multipleMode) {
+                this.$refs.table.clearSelection();
+            }
+        },
+        addRow() {
+            this.$router.push({
+                path: '/programmeEdit',
+                query: {
+                    ...this.$route.query
+                }
+            });
+        },
+        showRow(row) {
+            this.isShow = true;
+            this.$refs.public.dataApi(row.id);
+        },
+        download() {
+            this.downloading = true;
+
+            let data = {
+                sort: 'gradingOrganizationId,asc;organizationId,asc;examPoint,asc',
+                size: 2000,
+                query: {
+                    programmeStatus: 'SUBMIT'
+                }
+            };
+            if (this.$route.query.gid) {
+                data.query.gradingOrganizationId = this.$route.query.gid;
+            } else {
+                data.query.gradingOrganizationId = 0;
+            }
+            this.$axios
+                .get('/programme/excelGO', {
+                    responseType: 'blob',
+                    params: data
+                })
+                .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');
+        },
+        clearSearch() {
+            this.form = {};
+            this.getData();
+        },
+        getCode(value) {
+            return this.forTree(this.artTypes, value).code;
+        },
+        forTree(list, value) {
+            var result = null;
+            if (!list) {
+                return;
+            }
+            for (var i in list) {
+                if (result !== null) {
+                    break;
+                }
+                var item = list[i];
+                if (item.id == value) {
+                    result = item;
+                    break;
+                } else if (item.children && item.children.length > 0) {
+                    result = this.forTree(item.children, value);
+                }
+            }
+            return result;
+        },
+        // closeEvent() {
+        //     document.exitPictureInPicture();
+        // },
+        // playVideo(row) {
+        //     if (row.video) {
+        //         this.showViedo = true;
+        //         this.videoUrl = row.video;
+        //     } else {
+        //         this.$message.success('暂无视频');
+        //     }
+        // },
+        playImg(row) {
+            if (row.annex) {
+                this.showImg = true;
+                this.annex = row.annex;
+            } else {
+                this.$message.success('暂无图片');
+            }
+        },
+        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;
+        }
+    }
+};
+</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>

+ 255 - 129
src/main/vue/src/views/performance/ProgrammeList.vue

@@ -7,7 +7,6 @@
                         <el-form-item label="展演活动名称">
                         <el-form-item label="展演活动名称">
                             <el-select
                             <el-select
                                 v-model="performanceId"
                                 v-model="performanceId"
-                                clearable
                                 filterable
                                 filterable
                                 placeholder="展演活动名称"
                                 placeholder="展演活动名称"
                                 style="width: 100%"
                                 style="width: 100%"
@@ -22,51 +21,6 @@
                             </el-select>
                             </el-select>
                         </el-form-item>
                         </el-form-item>
                     </el-col>
                     </el-col>
-                    <el-col :span="8">
-                        <el-form-item label="考级机构名称">
-                            <el-select
-                                v-model="form.gradingOrganizationId"
-                                clearable
-                                filterable
-                                placeholder="考级机构"
-                                style="width: 100%"
-                            >
-                                <el-option
-                                    v-for="item in gradingOrganizationIdOptions"
-                                    :key="item.value"
-                                    :label="item.label"
-                                    :value="item.value"
-                                >
-                                </el-option>
-                            </el-select>
-                        </el-form-item>
-                    </el-col>
-                    <el-col :span="8">
-                        <el-form-item label="承办单位名称">
-                            <el-select
-                                v-model="form.organizationId"
-                                clearable
-                                filterable
-                                placeholder="承办单位"
-                                style="width: 100%"
-                            >
-                                <el-option
-                                    v-for="item in organizationIdOptions"
-                                    :key="item.value"
-                                    :label="item.label"
-                                    :value="item.value"
-                                >
-                                </el-option>
-                            </el-select>
-                        </el-form-item>
-                    </el-col>
-                </el-row>
-                <el-row>
-                    <el-col :span="8"
-                        ><el-form-item label="考级点名称">
-                            <el-input placeholder="考级点名称" v-model="search" clearable></el-input> </el-form-item
-                    ></el-col>
-
                     <el-col :span="8">
                     <el-col :span="8">
                         <el-form-item label="参赛专业">
                         <el-form-item label="参赛专业">
                             <el-cascader
                             <el-cascader
@@ -82,59 +36,153 @@
                             </el-cascader>
                             </el-cascader>
                         </el-form-item>
                         </el-form-item>
                     </el-col>
                     </el-col>
-                    <el-col :span="8"
-                        ><el-form-item label="参赛组别">
-                            <el-select v-model="form.competitionGroup" clearable filterable placeholder="参赛组别">
-                                <el-option
-                                    v-for="item in competitionGroupOptions"
-                                    :key="item.value"
-                                    :label="item.label"
-                                    :value="item.value"
-                                >
-                                </el-option>
-                            </el-select> </el-form-item
-                    ></el-col>
-                    <el-col :span="8"
-                        ><el-form-item label="参赛级别" v-if="form.competitionGroup">
-                            <el-select
-                                v-model="form.levelSettingId"
-                                clearable
-                                filterable
-                                placeholder="参赛级别"
-                                style="width: 100%"
-                                v-if="form.competitionGroup == 'SINGLE'"
-                            >
+                    <el-col :span="8">
+                        <el-form-item label="节目状态">
+                            <el-select v-model="form.programmeStatus" clearable>
                                 <el-option
                                 <el-option
-                                    v-for="item in levelSingleOptions"
+                                    v-for="item in programmeStatusOptions"
                                     :key="item.value"
                                     :key="item.value"
                                     :label="item.label"
                                     :label="item.label"
                                     :value="item.value"
                                     :value="item.value"
-                                >
-                                    <span style="float: left">{{ item.label }}</span>
-                                    <span style="float: right; color: #8492a6; font-size: 13px">{{ item.desc }}</span>
-                                </el-option>
+                                ></el-option>
                             </el-select>
                             </el-select>
-                            <el-select
-                                v-model="form.levelSettingId"
-                                clearable
-                                filterable
-                                placeholder="请选择"
-                                style="width: 100%"
-                                v-else
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+                <el-collapse-transition>
+                    <div v-show="showMore">
+                        <el-row>
+                            <el-col :span="8">
+                                <el-form-item label="考级机构名称">
+                                    <el-select
+                                        v-model="form.gradingOrganizationId"
+                                        clearable
+                                        filterable
+                                        placeholder="考级机构"
+                                        style="width: 100%"
+                                    >
+                                        <el-option
+                                            v-for="item in gradingOrganizationIdOptions"
+                                            :key="item.value"
+                                            :label="item.label"
+                                            :value="item.value"
+                                        >
+                                        </el-option>
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="8">
+                                <el-form-item label="承办单位名称">
+                                    <el-select
+                                        v-model="form.organizationId"
+                                        clearable
+                                        filterable
+                                        placeholder="承办单位"
+                                        style="width: 100%"
+                                    >
+                                        <el-option
+                                            v-for="item in organizationIdOptions"
+                                            :key="item.value"
+                                            :label="item.label"
+                                            :value="item.value"
+                                        >
+                                        </el-option>
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+
+                            <el-col :span="8"
+                                ><el-form-item label="考级点名称">
+                                    <el-input
+                                        placeholder="考级点名称"
+                                        v-model="search"
+                                        clearable
+                                    ></el-input> </el-form-item
+                            ></el-col>
+                        </el-row>
+                        <el-row>
+                            <el-col :span="8">
+                                <el-form-item label="节目名称">
+                                    <el-input placeholder="节目名称" v-model="form.name" clearable></el-input>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="8"
+                                ><el-form-item label="参赛组别">
+                                    <el-select
+                                        v-model="form.competitionGroup"
+                                        clearable
+                                        filterable
+                                        placeholder="参赛组别"
+                                    >
+                                        <el-option
+                                            v-for="item in competitionGroupOptions"
+                                            :key="item.value"
+                                            :label="item.label"
+                                            :value="item.value"
+                                        >
+                                        </el-option>
+                                    </el-select> </el-form-item
+                            ></el-col>
+
+                            <el-col :span="8"
+                                ><el-form-item label="参赛级别" v-if="form.competitionGroup">
+                                    <el-select
+                                        v-model="form.levelSettingId"
+                                        clearable
+                                        filterable
+                                        placeholder="参赛级别"
+                                        style="width: 100%"
+                                        v-if="form.competitionGroup == 'SINGLE'"
+                                    >
+                                        <el-option
+                                            v-for="item in levelSingleOptions"
+                                            :key="item.value"
+                                            :label="item.label"
+                                            :value="item.value"
+                                        >
+                                            <span style="float: left">{{ item.label }}</span>
+                                            <span style="float: right; color: #8492a6; font-size: 13px">{{
+                                                item.desc
+                                            }}</span>
+                                        </el-option>
+                                    </el-select>
+                                    <el-select
+                                        v-model="form.levelSettingId"
+                                        clearable
+                                        filterable
+                                        placeholder="请选择"
+                                        style="width: 100%"
+                                        v-else
+                                    >
+                                        <el-option
+                                            v-for="item in levelCollectiveOptions"
+                                            :key="item.value"
+                                            :label="item.label"
+                                            :value="item.value"
+                                        >
+                                            <span style="float: left">{{ item.label }}</span>
+                                            <span style="float: right; color: #8492a6; font-size: 13px">{{
+                                                item.desc
+                                            }}</span>
+                                        </el-option>
+                                    </el-select>
+                                </el-form-item></el-col
                             >
                             >
-                                <el-option
-                                    v-for="item in levelCollectiveOptions"
-                                    :key="item.value"
-                                    :label="item.label"
-                                    :value="item.value"
-                                >
-                                    <span style="float: left">{{ item.label }}</span>
-                                    <span style="float: right; color: #8492a6; font-size: 13px">{{ item.desc }}</span>
-                                </el-option>
-                            </el-select>
-                        </el-form-item></el-col
+                        </el-row>
+                    </div>
+                </el-collapse-transition>
+                <div style="width:100%;textAlign:center;margin-bottom:10px;">
+                    <el-button
+                        class="more"
+                        round
+                        type="primary"
+                        :plain="!showMore"
+                        :icon="showMore ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
+                        @click="showMore = !showMore"
+                        size="mini"
+                        >{{ showMore ? '隐藏查询区域' : '显示查询区域' }}</el-button
                     >
                     >
-                </el-row>
+                </div>
                 <el-form-item>
                 <el-form-item>
                     <el-button @click="getData" type="primary" icon="el-icon-search">查询 </el-button>
                     <el-button @click="getData" type="primary" icon="el-icon-search">查询 </el-button>
                     <el-button @click="clearSearch" type="primary">清空 </el-button>
                     <el-button @click="clearSearch" type="primary">清空 </el-button>
@@ -177,20 +225,41 @@
             <el-table-column prop="quantity" label="参赛人数" min-width="70"> </el-table-column>
             <el-table-column prop="quantity" label="参赛人数" min-width="70"> </el-table-column>
             <el-table-column prop="contact" label="联系人" min-width="68"> </el-table-column>
             <el-table-column prop="contact" label="联系人" min-width="68"> </el-table-column>
             <el-table-column prop="phone" label="联系电话" min-width="95"> </el-table-column>
             <el-table-column prop="phone" label="联系电话" min-width="95"> </el-table-column>
-            <el-table-column prop="gradingOrganization" label="考级机构" show-overflow-tooltip min-width="160">
+            <el-table-column prop="gradingOrganizationId" label="考级机构" show-overflow-tooltip min-width="130">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+                <template slot-scope="{ row }">
+                    <span>{{ row.gradingOrganization }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="organizationId" label="承办单位" min-width="170">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+                <template slot-scope="{ row }">
+                    <span>{{ row.organization }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="examPoint" label="考级点" min-width="160">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
             </el-table-column>
             </el-table-column>
-            <el-table-column prop="organization" label="承办单位" min-width="160"> </el-table-column>
-            <el-table-column prop="examPoint" label="考级点" min-width="160"> </el-table-column>
             <el-table-column
             <el-table-column
                 prop="programmeStatus"
                 prop="programmeStatus"
                 label="节目状态"
                 label="节目状态"
-                min-width="180"
+                min-width="90"
                 :formatter="programmeStatusFormatter"
                 :formatter="programmeStatusFormatter"
-            ></el-table-column>
+            >
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+            </el-table-column>
             <el-table-column label="操作" align="left" fixed="right" min-width="260">
             <el-table-column label="操作" align="left" fixed="right" min-width="260">
-                <template slot-scope="{ row }">
+                <template slot-scope="{ row, $index }">
                     <el-button @click="showRow(row)" size="mini" plain>查看</el-button>
                     <el-button @click="showRow(row)" size="mini" plain>查看</el-button>
-                    <el-button
+                    <!-- <el-button
                         type="warning"
                         type="warning"
                         @click="playImg(row)"
                         @click="playImg(row)"
                         v-if="
                         v-if="
@@ -223,8 +292,8 @@
                         size="mini"
                         size="mini"
                         plain
                         plain
                         >浏览图片</el-button
                         >浏览图片</el-button
-                    >
-                    <el-button type="warning" @click="playVideo(row)" v-else size="mini" plain>浏览视频</el-button>
+                    > -->
+                    <el-button type="warning" @click="playVideo(row, $index)" size="mini" plain>查看作品</el-button>
                     <el-button
                     <el-button
                         @click="audit(row, 'AUDIT_FAILED')"
                         @click="audit(row, 'AUDIT_FAILED')"
                         type="danger"
                         type="danger"
@@ -242,7 +311,6 @@
                         >撤回</el-button
                         >撤回</el-button
                     >
                     >
                     <!-- <el-button @click="showCode(row)" type="primary" size="mini" plain>查看二维码</el-button> -->
                     <!-- <el-button @click="showCode(row)" type="primary" size="mini" plain>查看二维码</el-button> -->
-                    <!-- <el-button @click="deleteRow(row)" type="danger" size="mini" plain>删除</el-button> -->
                 </template>
                 </template>
             </el-table-column>
             </el-table-column>
         </el-table>
         </el-table>
@@ -274,23 +342,61 @@
             </div>
             </div>
         </el-dialog>
         </el-dialog>
 
 
-        <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="70%">
+            <video
+                :src="programme.video"
+                controls
+                style="height: 600px; width: 85%; margin: 0 auto"
+                v-if="programme.video"
+            >
+                您的浏览器不支持 video 标签。
+            </video>
+            <div style="width: 85%; height:600px;margin: 0 auto" v-if="programme.annex">
+                <img style="max-height:100%; max-width: 100%; " :src="programme.annex" alt="" />
+            </div>
+            <div style="margin: 10px 10px">
+                <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-button @click="showViedo = false" size="mini">关闭</el-button>
+            </div>
+        </el-dialog> -->
+        <el-dialog
+            :title="programme.name"
+            class="videoDialog"
+            destroy-on-close
+            center
+            append-to-body
+            :visible.sync="showViedo"
+            width="auto"
+        >
             <video
             <video
-                :src="videoUrl"
-                controlsList="nodownload noremote footbar"
+                :src="programme.video"
                 controls
                 controls
-                style="height: 600px; width: 100%"
-                oncontextmenu="return false;"
-                ref="video"
-                v-if="showViedo"
+                style="max-height: 600px; max-width: 100%; margin: 0 auto"
+                v-if="programme.video"
             >
             >
                 您的浏览器不支持 video 标签。
                 您的浏览器不支持 video 标签。
             </video>
             </video>
+            <img
+                style="max-height: 600px; max-width: 100%; display: block; margin: auto"
+                :src="programme.annex"
+                alt=""
+                v-if="programme.annex"
+            />
+            <div style="display: block; margin: 10px;">
+                <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>
+            </div>
         </el-dialog>
         </el-dialog>
         <programme-log :dialogVisible="isShow" @close="isShow = false" ref="public"></programme-log>
         <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%; width: 100%;" :src="annex" alt="" />
-        </el-dialog>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
@@ -343,7 +449,10 @@ export default {
                 { label: '已提交', value: 'SUBMIT' },
                 { label: '已提交', value: 'SUBMIT' },
                 { label: '初选未通过', value: 'AUDIT_FAILED' },
                 { label: '初选未通过', value: 'AUDIT_FAILED' },
                 { label: '审核未通过', value: 'REVIEW_FAILED' }
                 { label: '审核未通过', value: 'REVIEW_FAILED' }
-            ]
+            ],
+            showMore: false,
+            programme: {},
+            index: 0
         };
         };
     },
     },
     created() {
     created() {
@@ -480,7 +589,6 @@ export default {
         },
         },
         beforeGetData() {
         beforeGetData() {
             let data = {
             let data = {
-                sort: 'createdAt,desc',
                 query: {}
                 query: {}
             };
             };
             if (this.form.competitionGroup) {
             if (this.form.competitionGroup) {
@@ -504,6 +612,12 @@ export default {
             if (this.review) {
             if (this.review) {
                 data.query.programmeStatus = 'SUBMIT';
                 data.query.programmeStatus = 'SUBMIT';
             }
             }
+            if (this.form.name) {
+                data.query.name = this.form.name;
+            }
+            if (this.form.programmeStatus) {
+                data.query.programmeStatus = this.form.programmeStatus;
+            }
             return data;
             return data;
         },
         },
         toggleMultipleMode(multipleMode) {
         toggleMultipleMode(multipleMode) {
@@ -528,7 +642,8 @@ export default {
             this.downloading = true;
             this.downloading = true;
 
 
             let data = {
             let data = {
-                sort: 'createdAt,desc',
+                sort: 'programmeStatus,desc',
+                size: 1000,
                 query: {}
                 query: {}
             };
             };
             if (this.form.competitionGroup) {
             if (this.form.competitionGroup) {
@@ -549,6 +664,12 @@ export default {
             if (this.performanceId) {
             if (this.performanceId) {
                 data.query.performanceId = this.performanceId;
                 data.query.performanceId = this.performanceId;
             }
             }
+            if (this.form.name) {
+                data.query.name = this.form.name;
+            }
+            if (this.form.programmeStatus) {
+                data.query.programmeStatus = this.form.programmeStatus;
+            }
 
 
             this.$axios
             this.$axios
                 .get('/programme/excel', {
                 .get('/programme/excel', {
@@ -599,14 +720,9 @@ export default {
         showCode(row) {
         showCode(row) {
             this.dialogCode = true;
             this.dialogCode = true;
             this.dialogUrl =
             this.dialogUrl =
-                'http://wljtest.izouma.com/h5/home?performanceId=' + row.performanceId + '&programmeId=' + row.id;
+                'http://yskj.njlyw.cn:8081/h5/home?performanceId=' + row.performanceId + '&programmeId=' + row.id;
         },
         },
         clearSearch() {
         clearSearch() {
-            // this.competitionGroup = '';
-            // this.levelSettingId = '';
-            // this.gradingOrganizationId = '';
-            // this.organizationId = '';
-            // this.specialtyId = '';
             this.form = {};
             this.form = {};
             this.getData();
             this.getData();
         },
         },
@@ -635,14 +751,14 @@ export default {
         // closeEvent() {
         // closeEvent() {
         //     document.exitPictureInPicture();
         //     document.exitPictureInPicture();
         // },
         // },
-        playVideo(row) {
-            if (row.video) {
-                this.showViedo = true;
-                this.videoUrl = row.video;
-            } else {
-                this.$message.success('暂无视频');
-            }
-        },
+        // playVideo(row) {
+        //     if (row.video) {
+        //         this.showViedo = true;
+        //         this.videoUrl = row.video;
+        //     } else {
+        //         this.$message.success('暂无视频');
+        //     }
+        // },
         playImg(row) {
         playImg(row) {
             if (row.annex) {
             if (row.annex) {
                 this.showImg = true;
                 this.showImg = true;
@@ -689,6 +805,16 @@ export default {
                     });
                     });
                     this.$set(row, 'loading', false);
                     this.$set(row, 'loading', false);
                 });
                 });
+        },
+        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;
         }
         }
     }
     }
 };
 };

+ 126 - 34
src/main/vue/src/views/performance/ProgrammeOrgList.vue

@@ -130,6 +130,7 @@
                 <el-form-item>
                 <el-form-item>
                     <el-button @click="canAdd" type="primary" icon="el-icon-search">查询 </el-button>
                     <el-button @click="canAdd" type="primary" icon="el-icon-search">查询 </el-button>
                     <el-button @click="addRow" type="primary" icon="el-icon-plus" v-if="add">添加 </el-button>
                     <el-button @click="addRow" type="primary" icon="el-icon-plus" v-if="add">添加 </el-button>
+                    <!-- <el-button @click="addRow" type="primary" icon="el-icon-plus">添加 </el-button> -->
                     <el-upload
                     <el-upload
                         :action="uploadUrl"
                         :action="uploadUrl"
                         :before-upload="beforeUpload"
                         :before-upload="beforeUpload"
@@ -139,9 +140,40 @@
                         :on-success="onSuccess"
                         :on-success="onSuccess"
                         class="uploader"
                         class="uploader"
                         :on-error="onfail"
                         :on-error="onfail"
+                        :loading="loading"
+                        :disabled="loading"
                     >
                     >
-                        <el-button slot="trigger" type="primary" icon="el-icon-upload2" v-if="add">批量上传</el-button>
+                        <el-button
+                            slot="trigger"
+                            type="primary"
+                            icon="el-icon-upload2"
+                            v-if="add"
+                            :loading="loading"
+                            :disabled="loading"
+                            >批量上传</el-button
+                        >
                     </el-upload>
                     </el-upload>
+                    <!-- <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-button
                     <el-button
                         @click="download"
                         @click="download"
                         type="primary"
                         type="primary"
@@ -167,7 +199,7 @@
             :height="tableHeight"
             :height="tableHeight"
         >
         >
             <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
             <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="id" label="编号" width="80" fixed="left"> </el-table-column>
             <el-table-column prop="name" label="节目名称" fixed="left"> </el-table-column>
             <el-table-column prop="name" label="节目名称" fixed="left"> </el-table-column>
             <el-table-column prop="specialty" label="参赛专业"> </el-table-column>
             <el-table-column prop="specialty" label="参赛专业"> </el-table-column>
             <el-table-column
             <el-table-column
@@ -182,28 +214,50 @@
             <el-table-column prop="quantity" label="参赛人数" min-width="70"> </el-table-column>
             <el-table-column prop="quantity" label="参赛人数" min-width="70"> </el-table-column>
             <el-table-column prop="contact" label="联系人" min-width="68"> </el-table-column>
             <el-table-column prop="contact" label="联系人" min-width="68"> </el-table-column>
             <!-- <el-table-column prop="phone" label="联系电话" min-width="95"> </el-table-column> -->
             <!-- <el-table-column prop="phone" label="联系电话" min-width="95"> </el-table-column> -->
-            <el-table-column prop="gradingOrganization" label="考级机构" show-overflow-tooltip min-width="160">
+            <el-table-column prop="gradingOrganizationId" label="考级机构" show-overflow-tooltip min-width="160">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+                <template slot-scope="{ row }">
+                    <span>{{ row.gradingOrganization }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="organizationId" label="承办单位" min-width="180">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+                <template slot-scope="{ row }">
+                    <span>{{ row.organization }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="examPoint" label="考级点" min-width="160">
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
             </el-table-column>
             </el-table-column>
-            <el-table-column prop="organization" label="承办单位" min-width="180"> </el-table-column>
             <el-table-column
             <el-table-column
                 prop="programmeStatus"
                 prop="programmeStatus"
                 label="节目状态"
                 label="节目状态"
                 min-width="180"
                 min-width="180"
                 :formatter="programmeStatusFormatter"
                 :formatter="programmeStatusFormatter"
-            ></el-table-column>
+            >
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
+            </el-table-column>
             <!-- <el-table-column prop="examPoint" label="考级点" min-width="160"> </el-table-column> -->
             <!-- <el-table-column prop="examPoint" label="考级点" min-width="160"> </el-table-column> -->
             <el-table-column label="操作" align="center" fixed="right" min-width="300">
             <el-table-column label="操作" align="center" fixed="right" min-width="300">
-                <template slot-scope="{ row }">
+                <template slot-scope="{ row, $index }">
                     <el-button @click="showRow(row)" size="mini" plain>查看</el-button>
                     <el-button @click="showRow(row)" size="mini" plain>查看</el-button>
                     <el-button
                     <el-button
                         type="success"
                         type="success"
                         @click="editRow(row)"
                         @click="editRow(row)"
                         size="mini"
                         size="mini"
                         plain
                         plain
-                        v-if="row.programmeStatus == 'INITIAL'"
+                        v-if="row.programmeStatus == 'INITIAL' && add"
                         >编辑</el-button
                         >编辑</el-button
                     >
                     >
-                    <el-button
+                    <!-- <el-button
                         type="warning"
                         type="warning"
                         @click="playImg(row)"
                         @click="playImg(row)"
                         v-if="
                         v-if="
@@ -237,7 +291,8 @@
                         plain
                         plain
                         >浏览图片</el-button
                         >浏览图片</el-button
                     >
                     >
-                    <el-button type="warning" @click="playVideo(row)" v-else size="mini" plain>浏览视频</el-button>
+                    <el-button type="warning" @click="playVideo(row)" v-else size="mini" plain>浏览视频</el-button> -->
+                    <el-button type="warning" @click="playVideo(row, $index)" size="mini" plain>查看作品</el-button>
                     <el-button
                     <el-button
                         @click="showCode(row)"
                         @click="showCode(row)"
                         type="primary"
                         type="primary"
@@ -278,21 +333,39 @@
             </div>
             </div>
         </el-dialog>
         </el-dialog>
 
 
-        <el-dialog class="videoDialog" destroy-on-close center append-to-body :visible.sync="showViedo" width="70%">
+        <el-dialog
+            :title="programme.name"
+            class="videoDialog"
+            destroy-on-close
+            center
+            append-to-body
+            :visible.sync="showViedo"
+            width="auto"
+        >
             <video
             <video
-                :src="videoUrl"
-                controlsList="nodownload noremote footbar"
+                :src="programme.video"
                 controls
                 controls
-                style="height: 100%; max-width: 100%"
-                oncontextmenu="return false;"
-                ref="video"
-                v-if="showViedo"
+                style="max-height: 600px; max-width: 100%; margin: 0 auto"
+                v-if="programme.video"
             >
             >
                 您的浏览器不支持 video 标签。
                 您的浏览器不支持 video 标签。
             </video>
             </video>
-        </el-dialog>
-        <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="max-height: 600px; max-width: 100%; display: block; margin: auto"
+                :src="programme.annex"
+                alt=""
+                v-if="programme.annex"
+            />
+            <div style="display: block; margin: 10px">
+                <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>
+            </div>
         </el-dialog>
         </el-dialog>
     </div>
     </div>
 </template>
 </template>
@@ -347,7 +420,10 @@ export default {
                 { label: '已提交', value: 'SUBMIT' },
                 { label: '已提交', value: 'SUBMIT' },
                 { label: '初选未通过', value: 'AUDIT_FAILED' },
                 { label: '初选未通过', value: 'AUDIT_FAILED' },
                 { label: '审核未通过', value: 'REVIEW_FAILED' }
                 { label: '审核未通过', value: 'REVIEW_FAILED' }
-            ]
+            ],
+            loading: false,
+            programme: {},
+            index: 0
         };
         };
     },
     },
     created() {
     created() {
@@ -477,7 +553,6 @@ export default {
         },
         },
         beforeGetData() {
         beforeGetData() {
             let data = {
             let data = {
-                sort: 'createdAt,desc',
                 query: {
                 query: {
                     organizationId: this.organization.id,
                     organizationId: this.organization.id,
                     performanceId: Number(this.$route.query.pid)
                     performanceId: Number(this.$route.query.pid)
@@ -540,7 +615,8 @@ export default {
             this.downloading = true;
             this.downloading = true;
 
 
             let data = {
             let data = {
-                sort: 'createdAt,desc',
+                sort: 'programmeStatus,desc',
+                size: 1000,
                 query: {
                 query: {
                     organizationId: this.organization.id
                     organizationId: this.organization.id
                 }
                 }
@@ -589,6 +665,7 @@ export default {
                 });
                 });
         },
         },
         downloadTemp() {
         downloadTemp() {
+            this.downloading = true;
             this.$axios
             this.$axios
                 .get('/programme/excelTemp', {
                 .get('/programme/excelTemp', {
                     responseType: 'blob'
                     responseType: 'blob'
@@ -636,7 +713,7 @@ export default {
         showCode(row) {
         showCode(row) {
             this.dialogCode = true;
             this.dialogCode = true;
             this.dialogUrl =
             this.dialogUrl =
-                'http://wljtest.izouma.com/h5/home?performanceId=' + row.performanceId + '&programmeId=' + row.id;
+                'http://yskj.njlyw.cn:8081/h5/home?performanceId=' + row.performanceId + '&programmeId=' + row.id;
         },
         },
         clearSearch() {
         clearSearch() {
             this.form = {};
             this.form = {};
@@ -667,11 +744,11 @@ export default {
         // closeEvent() {
         // closeEvent() {
         //     document.exitPictureInPicture();
         //     document.exitPictureInPicture();
         // },
         // },
-        playVideo(row) {
-            console.log(row);
-            this.showViedo = true;
-            this.videoUrl = row.video;
-        },
+        // playVideo(row) {
+        //     console.log(row);
+        //     this.showViedo = true;
+        //     this.videoUrl = row.video;
+        // },
         playImg(row) {
         playImg(row) {
             console.log(row);
             console.log(row);
             this.showImg = true;
             this.showImg = true;
@@ -680,11 +757,13 @@ export default {
         upload() {},
         upload() {},
         onfail(e) {
         onfail(e) {
             console.log(e);
             console.log(e);
-            this.$message.error('失败');
+            this.$message.error('失败:' + e);
+            this.loading = false;
             this.getData();
             this.getData();
         },
         },
         onSuccess() {
         onSuccess() {
             this.$message.success('上传成功');
             this.$message.success('上传成功');
+            this.loading = false;
             this.getData();
             this.getData();
         },
         },
         beforeUpload() {
         beforeUpload() {
@@ -692,18 +771,31 @@ export default {
                 confirmButtonText: '确定',
                 confirmButtonText: '确定',
                 cancelButtonText: '取消',
                 cancelButtonText: '取消',
                 type: 'warning'
                 type: 'warning'
+            }).then(() => {
+                this.loading = true;
             });
             });
         },
         },
         canAdd() {
         canAdd() {
             let data = this.performances.find(item => {
             let data = this.performances.find(item => {
                 return item.id == this.performanceId;
                 return item.id == this.performanceId;
             });
             });
-            if (data.endDate >= this.currentTime) {
-                this.add = true;
-            } else {
-                this.add = false;
-            }
+            // if (data.endDate >= this.currentTime) {
+            //     this.add = true;
+            // } else {
+            //     this.add = false;
+            // }
+            this.add = data.close;
             this.getData();
             this.getData();
+        },
+        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;
         }
         }
     }
     }
 };
 };

+ 3 - 7
src/main/vue/src/views/performance/ProgrammeScoreList.vue

@@ -183,7 +183,7 @@
                         <el-button
                         <el-button
                             size="mini"
                             size="mini"
                             @click="move(1)"
                             @click="move(1)"
-                            :disabled="(page - 1) * pageSize + index == totalElements - 1"
+                            :disabled="(page - 1) * pageSize + index == totalElements - 1 || index >= pageSize - 1"
                             >下一个</el-button
                             >下一个</el-button
                         >
                         >
                         <el-button @click="showViedo = false" size="mini">关闭</el-button>
                         <el-button @click="showViedo = false" size="mini">关闭</el-button>
@@ -464,12 +464,8 @@ export default {
         },
         },
         playVideo(row, index) {
         playVideo(row, index) {
             this.index = index;
             this.index = index;
-            if (row.video) {
-                this.showViedo = true;
-                this.programme = row;
-            } else {
-                this.$message.success('暂无视频');
-            }
+            this.showViedo = true;
+            this.programme = row;
         },
         },
         move(direction) {
         move(direction) {
             const end = direction + this.index;
             const end = direction + this.index;

+ 7 - 24
src/main/vue/src/views/rate/RateDistrictList.vue

@@ -280,25 +280,6 @@
             >
             >
             </el-pagination>
             </el-pagination>
         </div>
         </div>
-        <!-- <el-dialog title="退回缘由" :visible.sync="dialogDismiss" width="500px" center>
-            <div style="height: 150px;width:330px;margin:2px auto">
-                <label style="margin-right: 10px">退回缘由</label>
-                <el-select
-                    v-model="reason"
-                    filterable
-                    allow-create
-                    default-first-option
-                    clearable
-                    placeholder="请选择缘由"
-                    style="width: 70%"
-                >
-                    <el-option v-for="item in dismissReason" :key="item" :label="item" :value="item"> </el-option>
-                </el-select>
-                <div style="margin: 45px 0 0 240px">
-                    <el-button type="primary" @click="saveDismiss">确认</el-button>
-                </div>
-            </div>
-        </el-dialog> -->
         <el-dialog title="退回缘由" :visible.sync="dialogDismiss" width="500px" center>
         <el-dialog title="退回缘由" :visible.sync="dialogDismiss" width="500px" center>
             <div style="height: 150px;width:400px;margin:2px auto">
             <div style="height: 150px;width:400px;margin:2px auto">
                 <el-input
                 <el-input
@@ -354,7 +335,7 @@ export default {
         },
         },
         ...mapState(['userInfo']),
         ...mapState(['userInfo']),
         moreWidth() {
         moreWidth() {
-            let larges = ['FIRST_REVIEW_COMPLETED', 'FIRST_REVIEW_COMPLETED', 'ACCEPT'];
+            let larges = ['FIRST_REVIEW_COMPLETED', 'FIRST_REVIEW_COMPLETED', 'ACCEPT', 'REVIEW_DENY'];
             let mendus = ['SUBMIT_PAPER_MATERIALS'];
             let mendus = ['SUBMIT_PAPER_MATERIALS'];
 
 
             let list = [...this.tableData];
             let list = [...this.tableData];
@@ -363,9 +344,8 @@ export default {
                 if (larges.includes(list[i].status)) {
                 if (larges.includes(list[i].status)) {
                     size = 300;
                     size = 300;
                     break;
                     break;
-                }
-                if (mendus.includes(list[i].status)) {
-                    size = 200;
+                } else if (mendus.includes(list[i].status)) {
+                    size = 220;
                     continue;
                     continue;
                 }
                 }
             }
             }
@@ -393,7 +373,10 @@ export default {
             return '';
             return '';
         },
         },
         beforeGetData() {
         beforeGetData() {
-            let data = { sort: 'createdAt,desc', query: { submit: true, district: this.userInfo.district } };
+            let data = {
+                sort: 'sort,desc;score,desc;',
+                query: { submit: true, district: this.userInfo.district }
+            };
             if (this.search) {
             if (this.search) {
                 data.search = this.search;
                 data.search = this.search;
             }
             }

+ 2 - 30
src/main/vue/src/views/rate/RateDistrictListDone.vue

@@ -178,14 +178,6 @@
                     >
                     >
                         退回申请
                         退回申请
                     </el-button>
                     </el-button>
-                    <!-- <el-button
-                        @click="supervision(row.id)"
-                        type="success"
-                        size="mini"
-                        plain
-                        v-if="(row.status === 'ASSIGN_EXPERT') & display"
-                        >分配专家组</el-button
-                    > -->
                     <el-button
                     <el-button
                         v-if="row.status === 'SUBMIT_PAPER_MATERIALS'"
                         v-if="row.status === 'SUBMIT_PAPER_MATERIALS'"
                         type="success"
                         type="success"
@@ -220,25 +212,6 @@
             >
             >
             </el-pagination>
             </el-pagination>
         </div>
         </div>
-        <!-- <el-dialog title="退回缘由" :visible.sync="dialogDismiss" width="500px" center>
-            <div style="height: 150px;width:330px;margin:2px auto">
-                <label style="margin-right: 10px">退回缘由</label>
-                <el-select
-                    v-model="reason"
-                    filterable
-                    allow-create
-                    default-first-option
-                    clearable
-                    placeholder="请选择缘由"
-                    style="width: 70%"
-                >
-                    <el-option v-for="item in dismissReason" :key="item" :label="item" :value="item"> </el-option>
-                </el-select>
-                <div style="margin: 45px 0 0 240px">
-                    <el-button type="primary" @click="saveDismiss">确认</el-button>
-                </div>
-            </div>
-        </el-dialog> -->
         <el-dialog title="退回缘由" :visible.sync="dialogDismiss" width="500px" center>
         <el-dialog title="退回缘由" :visible.sync="dialogDismiss" width="500px" center>
             <div style="height: 150px;width:400px;margin:2px auto">
             <div style="height: 150px;width:400px;margin:2px auto">
                 <el-input
                 <el-input
@@ -305,7 +278,7 @@ export default {
                     break;
                     break;
                 }
                 }
                 if (mendus.includes(list[i].status)) {
                 if (mendus.includes(list[i].status)) {
-                    size = 200;
+                    size = 220;
                     continue;
                     continue;
                 }
                 }
             }
             }
@@ -341,7 +314,7 @@ export default {
             //     }
             //     }
             // };
             // };
             let data = {
             let data = {
-                sort: 'createdAt,desc',
+                sort: 'sort,desc;score,desc;',
                 query: {
                 query: {
                     submit: true,
                     submit: true,
                     district: this.userInfo.district,
                     district: this.userInfo.district,
@@ -350,7 +323,6 @@ export default {
                         'ASSIGN_EXPERT',
                         'ASSIGN_EXPERT',
                         'REVIEW_PENDING',
                         'REVIEW_PENDING',
                         'SUBMIT_GRADE',
                         'SUBMIT_GRADE',
-                        'SUBMIT_PAPER_MATERIALS',
                         'COLLECT_PAPER_MATERIALS',
                         'COLLECT_PAPER_MATERIALS',
                         'COMPLETE'
                         'COMPLETE'
                     ]
                     ]

+ 10 - 24
src/main/vue/src/views/rate/RateDistrictListPending.vue

@@ -212,25 +212,6 @@
             >
             >
             </el-pagination>
             </el-pagination>
         </div>
         </div>
-        <!-- <el-dialog title="退回缘由" :visible.sync="dialogDismiss" width="500px" center>
-            <div style="height: 150px;width:330px;margin:2px auto">
-                <label style="margin-right: 10px">退回缘由</label>
-                <el-select
-                    v-model="reason"
-                    filterable
-                    allow-create
-                    default-first-option
-                    clearable
-                    placeholder="请选择缘由"
-                    style="width: 70%"
-                >
-                    <el-option v-for="item in dismissReason" :key="item" :label="item" :value="item"> </el-option>
-                </el-select>
-                <div style="margin: 45px 0 0 240px">
-                    <el-button type="primary" @click="saveDismiss">确认</el-button>
-                </div>
-            </div>
-        </el-dialog> -->
         <el-dialog title="退回缘由" :visible.sync="dialogDismiss" width="500px" center>
         <el-dialog title="退回缘由" :visible.sync="dialogDismiss" width="500px" center>
             <div style="height: 150px;width:400px;margin:2px auto">
             <div style="height: 150px;width:400px;margin:2px auto">
                 <el-input
                 <el-input
@@ -295,9 +276,8 @@ export default {
                 if (larges.includes(list[i].status)) {
                 if (larges.includes(list[i].status)) {
                     size = 300;
                     size = 300;
                     break;
                     break;
-                }
-                if (mendus.includes(list[i].status)) {
-                    size = 200;
+                } else if (mendus.includes(list[i].status)) {
+                    size = 220;
                     continue;
                     continue;
                 }
                 }
             }
             }
@@ -326,11 +306,17 @@ export default {
         },
         },
         beforeGetData() {
         beforeGetData() {
             let data = {
             let data = {
-                sort: 'createdAt,desc',
+                sort: 'sort,desc;score,desc;',
                 query: {
                 query: {
                     submit: true,
                     submit: true,
                     district: this.userInfo.district,
                     district: this.userInfo.district,
-                    status: ['FIRST_REVIEW_PENDING', 'ACCEPT', 'FIRST_REVIEW_COMPLETED', 'REVIEW_DENY']
+                    status: [
+                        'FIRST_REVIEW_PENDING',
+                        'ACCEPT',
+                        'FIRST_REVIEW_COMPLETED',
+                        'REVIEW_DENY',
+                        'SUBMIT_PAPER_MATERIALS'
+                    ]
                 }
                 }
             };
             };
             if (this.search) {
             if (this.search) {

+ 3 - 62
src/main/vue/src/views/rate/RateList.vue

@@ -1,68 +1,6 @@
 <template>
 <template>
     <div class="list-view">
     <div class="list-view">
         <div class="filters-container">
         <div class="filters-container">
-            <!-- <el-input placeholder="输入关键字" v-model="search" clearable class="filter-item"></el-input>
-             <el-button @click="addRow" type="primary" icon="el-icon-plus" class="filter-item">创建申请 </el-button> -->
-            <!-- <el-button
-                @click="download"
-                type="primary"
-                icon="el-icon-download"
-                :loading="downloading"
-                class="filter-item"
-                :disabled="totalElements <= 0"
-                >导出EXCEL
-            </el-button>
-            <el-select v-model="year" placeholder="请选择年度" class="filter-item" clearable>
-                <el-option v-for="item in years" :key="item" :value="item" :label="item + '年'"></el-option>
-            </el-select>
-            <el-select v-model="agency" placeholder="所属考级机构" multiple class="filter-item">
-                <el-option
-                    v-for="(item, index) in examination"
-                    :key="index"
-                    :value="item.value"
-                    :label="item.label"
-                ></el-option>
-            </el-select>
-            <el-input
-                placeholder="输入承办单位名称"
-                v-model="search"
-                clearable
-                class="filter-item"
-                @change="getData"
-            ></el-input>
-            <el-select
-                style="width: 220px"
-                v-model="status"
-                placeholder="请选择的状态"
-                class="filter-item"
-                multiple
-                clearable
-                @change="getData"
-            >
-                <el-option
-                    v-for="item in statusOptions"
-                    :key="item.value"
-                    :label="item.label"
-                    :value="item.value"
-                ></el-option>
-            </el-select>
-            <el-select
-                style="width: 220px"
-                v-model="grade"
-                placeholder="请选择的等级"
-                class="filter-item"
-                multiple
-                clearable
-                @change="getData"
-            >
-                <el-option
-                    v-for="item in gradeOptions"
-                    :key="item.value"
-                    :label="item.label"
-                    :value="item.value"
-                ></el-option>
-            </el-select> -->
-            <!-- <el-button @click="getData" type="primary" icon="el-icon-search" class="filter-item">搜索 </el-button> -->
             <div>
             <div>
                 <el-col :span="7">
                 <el-col :span="7">
                     <span class="span-size">申请年度</span>
                     <span class="span-size">申请年度</span>
@@ -193,6 +131,9 @@
                     <span v-if="row.score">{{ row.score }}</span>
                     <span v-if="row.score">{{ row.score }}</span>
                     <span v-else>暂无</span>
                     <span v-else>暂无</span>
                 </template>
                 </template>
+                <template slot="header" slot-scope="{ column }">
+                    <sortable-header :column="column" :current-sort="sort" @changeSort="changeSort"> </sortable-header>
+                </template>
             </el-table-column>
             </el-table-column>
             <el-table-column prop="grade" label="等级">
             <el-table-column prop="grade" label="等级">
                 <template slot-scope="{ row }">
                 <template slot-scope="{ row }">

+ 35 - 1
src/main/vue/src/views/rate/RateListDone.vue

@@ -122,6 +122,12 @@
                         :disabled="totalElements <= 0"
                         :disabled="totalElements <= 0"
                         >导出EXCEL
                         >导出EXCEL
                     </el-button>
                     </el-button>
+                    <el-button type="primary" :loading="downloading" class="filter-item" @click="batchSendSms(true)"
+                        >公告短信通知
+                    </el-button>
+                    <el-button type="primary" :loading="downloading" class="filter-item" @click="batchSendSms(false)"
+                        >提交材料短信通知
+                    </el-button>
                 </el-col>
                 </el-col>
             </div>
             </div>
         </div>
         </div>
@@ -345,7 +351,7 @@ export default {
         },
         },
         beforeGetData() {
         beforeGetData() {
             let data = {
             let data = {
-                sort: 'sort,desc;createdAt,desc',
+                sort: 'sort,desc;score,desc;createdAt,desc',
                 query: {
                 query: {
                     submit: true,
                     submit: true,
                     status: ['REVIEW_PENDING', 'SUBMIT_PAPER_MATERIALS', 'COMPLETE']
                     status: ['REVIEW_PENDING', 'SUBMIT_PAPER_MATERIALS', 'COMPLETE']
@@ -603,6 +609,34 @@ export default {
                     });
                     });
                     this.$set(row, 'loading', false);
                     this.$set(row, 'loading', false);
                 });
                 });
+        },
+        batchSendSms(res) {
+            this.$confirm('发送短信后不可撤回,确认发送吗?', '提示', {
+                confirmButtonText: '确认',
+                cancelButtonText: '取消',
+                type: 'warning'
+            })
+                .then(() => {
+                    this.$http
+                        .post('/rate/batchSendSms', {
+                            announcement: res
+                        })
+                        .then(res => {
+                            this.$message.success('发送成功');
+                            this.getData();
+                        })
+                        .catch(e => {
+                            console.log(e);
+                            this.$message.error(e.error);
+                        });
+                })
+                .catch(() => {
+                    this.$message({
+                        type: 'info',
+                        message: '已取消'
+                    });
+                    this.$set(row, 'loading', false);
+                });
         }
         }
     }
     }
 };
 };

+ 56 - 1
src/main/vue/src/views/rate/RateListPending.vue

@@ -122,6 +122,7 @@
                         :disabled="totalElements <= 0"
                         :disabled="totalElements <= 0"
                         >导出EXCEL
                         >导出EXCEL
                     </el-button>
                     </el-button>
+                    <el-button @click="dialogRatio = true" type="primary">设置等级</el-button>
                 </el-col>
                 </el-col>
             </div>
             </div>
         </div>
         </div>
@@ -256,6 +257,35 @@
                 </div>
                 </div>
             </div>
             </div>
         </el-dialog>
         </el-dialog>
+        <el-dialog title="等级比例" :visible.sync="dialogRatio" width="500px" center>
+            <div style="height: 150px;width:400px;margin:0 0 2px 80px">
+                <el-form :form="ratioForm">
+                    <el-form-item label="优秀比例(%)">
+                        <el-input-number
+                            v-model="ratioForm.excellent"
+                            :min="0"
+                            :max="100"
+                            @change="changeEligible"
+                            style="width: 160px"
+                        ></el-input-number>
+                    </el-form-item>
+                    <el-form-item label="合格比例(%)">
+                        <el-input-number
+                            v-model="ratioForm.eligible"
+                            :min="0"
+                            :max="100"
+                            @change="changeExcellent"
+                            style="width: 160px"
+                        ></el-input-number>
+                    </el-form-item>
+                    <el-form-item>
+                        <el-button style="margin-left: 170px" type="primary" size="mini" @click="gradeRatio"
+                            >确定</el-button
+                        >
+                    </el-form-item>
+                </el-form>
+            </div>
+        </el-dialog>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
@@ -291,7 +321,9 @@ export default {
             year: '',
             year: '',
             districts: [],
             districts: [],
             district: '',
             district: '',
-            dateRange: ''
+            dateRange: '',
+            dialogRatio: false,
+            ratioForm: {}
         };
         };
     },
     },
     created() {
     created() {
@@ -612,6 +644,29 @@ export default {
                     });
                     });
                     this.$set(row, 'loading', false);
                     this.$set(row, 'loading', false);
                 });
                 });
+        },
+        changeEligible(res) {
+            this.ratioForm.eligible = 100 - res;
+        },
+        changeExcellent(res) {
+            this.ratioForm.excellent = 100 - res;
+        },
+        gradeRatio() {
+            this.$http
+                .post('/rate/gradeRatio', {
+                    excellent: this.ratioForm.excellent,
+                    eligible: this.ratioForm.eligible
+                })
+                .then(res => {
+                    this.$message.success('等级设置成功');
+                    this.getData();
+                    this.dialogRatio = false;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.dialogRatio = false;
+                    this.$message.error(e.error);
+                });
         }
         }
     }
     }
 };
 };

+ 49 - 6
src/main/vue/src/views/rate/RateOrganizerList.vue

@@ -49,7 +49,7 @@
                     <span v-else><el-tag type="info">暂无</el-tag></span>
                     <span v-else><el-tag type="info">暂无</el-tag></span>
                 </template>
                 </template>
             </el-table-column>
             </el-table-column>
-            <el-table-column label="操作" align="center" fixed="right" min-width="150">
+            <el-table-column label="操作" align="center" fixed="right" min-width="160">
                 <template slot-scope="{ row }">
                 <template slot-scope="{ row }">
                     <el-button @click="editRow(row)" type="primary" size="mini" plain>
                     <el-button @click="editRow(row)" type="primary" size="mini" plain>
                         <span v-if="row.status == 'FIRST_REVIEW_DENY' || !row.submit">编辑资料</span>
                         <span v-if="row.status == 'FIRST_REVIEW_DENY' || !row.submit">编辑资料</span>
@@ -65,7 +65,7 @@
                         >撤回
                         >撤回
                     </el-button>
                     </el-button>
                     <el-button
                     <el-button
-                        @click="word(row)"
+                        @click="aletrLog(row)"
                         type="primary"
                         type="primary"
                         :loading="downloading"
                         :loading="downloading"
                         size="mini"
                         size="mini"
@@ -98,6 +98,22 @@
             >
             >
             </el-pagination>
             </el-pagination>
         </div>
         </div>
+        <el-dialog title="提示信息" width="500px" :visible.sync="dialogVisible" center>
+            <div>
+                <span class="content"
+                    >下载文件需要合并所有上传的信息,并转成pdf,可能会比较大。如遇无法下载,可试以下方法:</span
+                ><br />
+                <span class="content">1.点击复制链接按钮,复制下载地址用任何其他方式下载;</span><br />
+                <span class="content">2.刷新页面,查看网络是否流畅;</span><br />
+                <span class="content">3.更换最新的谷歌(chrome)浏览器,再点击下载文件;</span><br />
+                <span class="content">4.如还是长时间没有反应,可联系技术支持微信:PrettyFairyLi;</span><br />
+                <span class="content">链接地址:{{ rate.pdfUrl }}</span>
+            </div>
+            <div style="float: right; padding: 10px;">
+                <el-button size="mini" @click="copy">复制链接</el-button>
+                <el-button @click="word()" type="primary" size="mini">继续下载</el-button>
+            </div>
+        </el-dialog>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
@@ -114,7 +130,9 @@ export default {
             search: '',
             search: '',
             url: '/rate/all',
             url: '/rate/all',
             downloading: false,
             downloading: false,
-            canApply: false
+            canApply: false,
+            dialogVisible: false,
+            rate: {}
         };
         };
     },
     },
     created() {
     created() {
@@ -214,10 +232,15 @@ export default {
                     }
                     }
                 });
                 });
         },
         },
-        word(row) {
+        aletrLog(row) {
+            this.rate = row;
+            this.dialogVisible = true;
+        },
+        word() {
             this.downloading = true;
             this.downloading = true;
+            console.log(this.rate);
             this.$axios
             this.$axios
-                .get('/rate/exportPdf/' + row.id, { responseType: 'blob' })
+                .get('/rate/exportPdf/' + this.rate.id, { responseType: 'blob' })
                 .then(res => {
                 .then(res => {
                     console.log(res);
                     console.log(res);
                     this.downloading = false;
                     this.downloading = false;
@@ -233,6 +256,8 @@ export default {
                     console.log(e);
                     console.log(e);
                     this.downloading = false;
                     this.downloading = false;
                     this.$message.error(e.error);
                     this.$message.error(e.error);
+                    this.rate = {};
+                    this.dialogVisible = false;
                 });
                 });
             // this.$axios
             // this.$axios
             //     .get('/rate/export/' + row.id)
             //     .get('/rate/export/' + row.id)
@@ -272,8 +297,26 @@ export default {
                         this.$message.error((e || {}).error || '撤回失败');
                         this.$message.error((e || {}).error || '撤回失败');
                     }
                     }
                 });
                 });
+        },
+        copy() {
+            this.$copyText(this.rate.pdfUrl).then(
+                e => {
+                    this.$message.success('复制成功');
+                },
+                e => {
+                    this.$message.warning('复制失败');
+                }
+            );
         }
         }
     }
     }
 };
 };
 </script>
 </script>
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+.content {
+    font-size: 14px;
+    line-height: 25px;
+}
+/deep/ .el-dialog {
+    height: 330px;
+}
+</style>

+ 0 - 1
src/main/vue/src/views/user/UserList.vue

@@ -101,7 +101,6 @@ export default {
             if (this.search) {
             if (this.search) {
                 data.search = this.search;
                 data.search = this.search;
                 data.page = 0;
                 data.page = 0;
-                console.log();
             }
             }
             console.log(this.getAdmin());
             console.log(this.getAdmin());
             if (!this.getAdmin()) {
             if (!this.getAdmin()) {

+ 103 - 0
src/main/vue/src/widgets/BoardWidget.vue

@@ -0,0 +1,103 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle" ref="container">
+        <template slot="header">
+            通知通告
+        </template>
+        <div class="boardList" :style="{ height: height + 'px' }">
+            <router-link
+                :underline="false"
+                :to="{
+                    path: '/announcementDetail',
+                    query: {
+                        id: item.id
+                    }
+                }"
+                class="board-item"
+                v-for="(item, index) in tableData"
+                :key="index"
+            >
+                <span>{{ item.title }}</span>
+                <span>{{ item.createdAt }}</span>
+            </router-link>
+            <div class="empty" v-if="isEmpty">暂无数据</div>
+        </div>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from './WidgetCard';
+
+export default {
+    data() {
+        return {
+            bodyStyle: {},
+            tableData: [],
+            height: 200,
+            isEmpty: false
+        };
+    },
+    components: {
+        WidgetCard
+    },
+    mounted() {
+        this.$nextTick(() => {
+            this.height = this.$refs.container.$el.offsetHeight - 100;
+        });
+        this.$http
+            .post('/announcement/all', { size: 10, query: { type: 'NOTIFICATION' } }, { body: 'json' })
+            .then(res => {
+                this.tableData = res.content;
+                this.isEmpty = res.empty;
+            });
+    }
+};
+</script>
+<style lang="less" scoped>
+.info {
+    flex-grow: 1;
+    text-align: right;
+    .text {
+        color: #999;
+        font-size: 16px;
+        margin-bottom: 12px;
+    }
+    .num {
+        font-size: 20px;
+        color: #333;
+    }
+}
+.boardList {
+    .board-item + .board-item {
+        margin-top: 20px;
+    }
+    .board-item {
+        font-size: 14px;
+        margin-right: 15px;
+        line-height: 20px;
+        display: flex;
+        justify-content: space-between;
+
+        span {
+            &:first-child {
+                color: #000;
+                font-weight: bold;
+                white-space: nowrap;
+                text-overflow: ellipsis;
+                overflow: hidden;
+                word-break: break-all;
+            }
+            &:last-child {
+                color: #999;
+                flex-shrink: 0;
+            }
+        }
+    }
+    overflow: auto;
+}
+
+.empty {
+    font-size: 12px;
+    color: #999;
+    text-align: center;
+    padding: 50px;
+}
+</style>

+ 101 - 0
src/main/vue/src/widgets/PolicyWidget.vue

@@ -0,0 +1,101 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle" ref="container">
+        <template slot="header">
+            政策文件
+        </template>
+        <div class="boardList" :style="{ height: height + 'px' }">
+            <router-link
+                :underline="false"
+                :to="{
+                    path: '/announcementDetail',
+                    query: {
+                        id: item.id
+                    }
+                }"
+                class="board-item"
+                v-for="(item, index) in tableData"
+                :key="index"
+            >
+                <span>{{ item.title }}</span>
+                <span>{{ item.createdAt }}</span>
+            </router-link>
+            <div class="empty" v-if="isEmpty">暂无数据</div>
+        </div>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from './WidgetCard';
+
+export default {
+    data() {
+        return {
+            bodyStyle: {},
+            tableData: [],
+            height: 200,
+            isEmpty: false
+        };
+    },
+    components: {
+        WidgetCard
+    },
+    mounted() {
+        this.$nextTick(() => {
+            this.height = this.$refs.container.$el.offsetHeight - 100;
+        });
+        this.$http.post('/announcement/all', { size: 10, query: { type: 'POLICY' } }, { body: 'json' }).then(res => {
+            this.tableData = res.content;
+            this.isEmpty = res.empty;
+        });
+    }
+};
+</script>
+<style lang="less" scoped>
+.info {
+    flex-grow: 1;
+    text-align: right;
+    .text {
+        color: #999;
+        font-size: 16px;
+        margin-bottom: 12px;
+    }
+    .num {
+        font-size: 20px;
+        color: #333;
+    }
+}
+.boardList {
+    .board-item + .board-item {
+        margin-top: 20px;
+    }
+    .board-item {
+        font-size: 14px;
+        margin-right: 15px;
+        line-height: 20px;
+        display: flex;
+        justify-content: space-between;
+
+        span {
+            &:first-child {
+                color: #000;
+                font-weight: bold;
+                white-space: nowrap;
+                text-overflow: ellipsis;
+                overflow: hidden;
+                word-break: break-all;
+            }
+            &:last-child {
+                color: #999;
+                flex-shrink: 0;
+            }
+        }
+    }
+    overflow: auto;
+}
+
+.empty {
+    font-size: 12px;
+    color: #999;
+    text-align: center;
+    padding: 50px;
+}
+</style>

+ 16 - 0
src/main/vue/yarn.lock

@@ -2349,6 +2349,15 @@ cli-width@^2.0.0:
   resolved "https://registry.npm.taobao.org/cli-width/download/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
   resolved "https://registry.npm.taobao.org/cli-width/download/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
   integrity sha1-sEM9C06chH7xiGik7xb9X8gnHEg=
   integrity sha1-sEM9C06chH7xiGik7xb9X8gnHEg=
 
 
+clipboard@^2.0.0:
+  version "2.0.8"
+  resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.8.tgz#ffc6c103dd2967a83005f3f61976aa4655a4cdba"
+  integrity sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==
+  dependencies:
+    good-listener "^1.2.2"
+    select "^1.1.2"
+    tiny-emitter "^2.0.0"
+
 clipboard@^2.0.6:
 clipboard@^2.0.6:
   version "2.0.6"
   version "2.0.6"
   resolved "https://registry.npm.taobao.org/clipboard/download/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376"
   resolved "https://registry.npm.taobao.org/clipboard/download/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376"
@@ -8379,6 +8388,13 @@ vue-cli-plugin-style-resources-loader@^0.1.4:
   resolved "https://registry.npm.taobao.org/vue-cli-plugin-style-resources-loader/download/vue-cli-plugin-style-resources-loader-0.1.4.tgz#6087a86132ea8125aa89e5f8e0a978fbc8cf6f59"
   resolved "https://registry.npm.taobao.org/vue-cli-plugin-style-resources-loader/download/vue-cli-plugin-style-resources-loader-0.1.4.tgz#6087a86132ea8125aa89e5f8e0a978fbc8cf6f59"
   integrity sha1-YIeoYTLqgSWqieX44Kl4+8jPb1k=
   integrity sha1-YIeoYTLqgSWqieX44Kl4+8jPb1k=
 
 
+vue-clipboard2@^0.3.3:
+  version "0.3.3"
+  resolved "https://registry.yarnpkg.com/vue-clipboard2/-/vue-clipboard2-0.3.3.tgz#331fec85f9d4f175eb0d4feaef4d77338562af36"
+  integrity sha512-aNWXIL2DKgJyY/1OOeITwAQz1fHaCIGvUFHf9h8UcoQBG5a74MkdhS/xqoYe7DNZdQmZRL+TAdIbtUs9OyVjbw==
+  dependencies:
+    clipboard "^2.0.0"
+
 vue-eslint-parser@^7.0.0:
 vue-eslint-parser@^7.0.0:
   version "7.1.0"
   version "7.1.0"
   resolved "https://registry.npm.taobao.org/vue-eslint-parser/download/vue-eslint-parser-7.1.0.tgz?cache=0&sync_timestamp=1589539313907&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-eslint-parser%2Fdownload%2Fvue-eslint-parser-7.1.0.tgz#9cdbcc823e656b087507a1911732b867ac101e83"
   resolved "https://registry.npm.taobao.org/vue-eslint-parser/download/vue-eslint-parser-7.1.0.tgz?cache=0&sync_timestamp=1589539313907&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-eslint-parser%2Fdownload%2Fvue-eslint-parser-7.1.0.tgz#9cdbcc823e656b087507a1911732b867ac101e83"

+ 13 - 2
src/test/java/com/izouma/wenlvju/repo/RepoTest.java

@@ -206,7 +206,18 @@ public class RepoTest extends ApplicationTests {
 
 
     @Test
     @Test
     public void test6() {
     public void test6() {
-        String phone = "18205083565";
-        System.out.println(phone.replace(phone.substring(3, phone.length() - 4), "****"));
+//        String phone = "18205083565";
+//        System.out.println(phone.replace(phone.substring(3, phone.length() - 4), "****"));
+        int sum1 = Math.round(75 * 20 / 100);
+        System.out.println(sum1);
+        int sum2 = Math.round(75 * 80 / 100);
+        System.out.println(sum1 + sum2);
+    }
+
+    @Test
+    public void test7(){
+        String url = "http://yskj.njlyw.cn:8081/files/pdf/material12409.pdf";
+        int start = url.indexOf("/pdf");
+        System.out.println(url.substring(start));
     }
     }
 }
 }

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

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

+ 60 - 28
src/test/java/com/izouma/wenlvju/service/RateServiceTest.java

@@ -4,6 +4,7 @@ package com.izouma.wenlvju.service;
 import com.github.kevinsawicki.http.HttpRequest;
 import com.github.kevinsawicki.http.HttpRequest;
 import com.izouma.wenlvju.ApplicationTests;
 import com.izouma.wenlvju.ApplicationTests;
 import com.izouma.wenlvju.domain.Rate;
 import com.izouma.wenlvju.domain.Rate;
+import com.izouma.wenlvju.enums.RateStatus;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.repo.RateRepo;
 import com.izouma.wenlvju.repo.RateRepo;
 import com.lowagie.text.Document;
 import com.lowagie.text.Document;
@@ -33,32 +34,44 @@ public class RateServiceTest extends ApplicationTests {
     }
     }
 
 
     @Test
     @Test
-    public void test2() throws UnsupportedEncodingException {
+    public void test2() {
 
 
-        Rate rate = rateRepo.findById(625L).orElseThrow(new BusinessException("无记录"));
-        List<InputStream> files = rateService.upLoad1(rate);
+//        Rate rate = rateRepo.findById(11825L).orElseThrow(new BusinessException("无记录"));
+        List<Rate> rates = rateRepo.findAllByStatusAndYearOrderByScoreDesc(RateStatus.COLLECT_PAPER_MATERIALS, "2021");
+        rates.forEach(rate -> {
 
 
-        String targetPath = "/Users/qiufangchao/Desktop/result.pdf";
-        // pdf合并工具类
-        PDFMergerUtility mergePdf = new PDFMergerUtility();
-//        for (File f : files) {
-//            if (f.exists() && f.isFile()) {
-        // 循环添加要合并的pdf
-//                mergePdf.addSource(f);
-//            }
-//        }
-        mergePdf.addSources(files);
-        // 设置合并生成pdf文件名称
-        mergePdf.setDestinationFileName(targetPath);
-        // 合并pdf
-        try {
-            mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
-            for (InputStream is : files) {
-                is.close();
+            List<InputStream> files = null;
+            try {
+                files = rateService.upLoad1(rate);
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
             }
             }
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
+
+            String targetPath = "/Users/qiufangchao/Desktop/rate/material" + rate.getId() + ".pdf";
+//            if (!new File(targetPath).exists()) {
+            // pdf合并工具类
+            PDFMergerUtility mergePdf = new PDFMergerUtility();
+            //for (File f : files) {
+            //      if (f.exists() && f.isFile()) {
+            // 循环添加要合并的pdf
+            //           mergePdf.addSource(f);
+            //      }
+            // }
+            mergePdf.addSources(files);
+            // 设置合并生成pdf文件名称
+            mergePdf.setDestinationFileName(targetPath);
+            // 合并pdf
+            try {
+                mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
+                for (InputStream is : files) {
+                    is.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+//            }
+        });
+
 //        System.out.println(writer.toString());
 //        System.out.println(writer.toString());
 //        new File(targetPath);
 //        new File(targetPath);
 
 
@@ -122,9 +135,6 @@ public class RateServiceTest extends ApplicationTests {
 
 
     @Test
     @Test
     public void test8() {
     public void test8() {
-
-//        String img = "https://ticket-exchange.oss-cn-hangzhou.aliyuncs.com/image/2021-04-29-12-39-59rzhrQYhu.jpg";
-
         Rate rate = rateRepo.findById(625L).orElseThrow(new BusinessException("wu"));
         Rate rate = rateRepo.findById(625L).orElseThrow(new BusinessException("wu"));
         List<String> imageUrllist = rate.getBusiness();
         List<String> imageUrllist = rate.getBusiness();
 
 
@@ -165,9 +175,31 @@ public class RateServiceTest extends ApplicationTests {
         System.out.println(rateService.reviewTimesMessage(rate));
         System.out.println(rateService.reviewTimesMessage(rate));
     }
     }
 
 
-
     @Test
     @Test
     public void test10() {
     public void test10() {
-        System.out.println(rateRepo.countByExpertId(700l));
+        System.out.println(rateRepo.countByExpertId(700L));
     }
     }
+
+    @Test
+    public void test11() {
+        Rate rate = rateRepo.findById(11825L).orElseThrow(new BusinessException("无记录"));
+        try {
+            rateService.mergePdf(rate);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    @Test
+    public void test12() {
+        List<Rate> rates = rateRepo.findAllByStatusAndYearOrderByScoreDesc(RateStatus.SUBMIT_PAPER_MATERIALS, "2021");
+        rates.forEach(rate -> {
+            String url = "/Users/qiufangchao/Desktop/rate/material" + rate.getId() + ".pdf";
+            rate.setPdfUrl(url);
+        });
+        rateRepo.saveAll(rates);
+
+    }
+
 }
 }

+ 5 - 3
src/test/java/com/izouma/wenlvju/service/sms/NjwlSmsServiceTest.java

@@ -11,10 +11,12 @@ public class NjwlSmsServiceTest extends ApplicationTests {
 
 
     @Test
     @Test
     public void test() {
     public void test() {
-        njwlSmsService.sendSms("19951988293", "test");
+//        njwlSmsService.sendSms("15605172272", "【宁艺通】2021年南京考级承办单位等级评定工作已完成,拟评定结果已在南京市文化和旅游局官网公示。请你单位登陆“宁艺通”等级评定系统下载打印等级评定材料,并于11月15日前将纸质申报表及完整佐证材料(各2份)送属地区文化和旅游局履行线下审核程序,逾期不送,作自动放弃处理。");
+        String body = "尊敬的调研对象:\n" +
+                "您好,为贯彻落实国家、省、市关于“双减”工作相关文件精神,了解和掌握我市文化艺术类校外培训机构相关情况,市文旅局决定开展全市文化艺术类校外培训机构网上问卷调查,如从事文化艺术类校外培训,请登录:http://wljtest.izouma.com/h5/trainingInstitution,填写调查问卷,如不从事文化艺术类校外培训,请忽略本条信息,谢谢。\n";
+        ;
+        njwlSmsService.sendSms("19951988293", body);
         // {"expiryDate":"1623808467934","tokenKey":"1fb4796840d8a7b8d43e022e5a1f693c","data":{"phone":"19951988293","message":"test"},"appId":"189610","operationType":"ADD"}
         // {"expiryDate":"1623808467934","tokenKey":"1fb4796840d8a7b8d43e022e5a1f693c","data":{"phone":"19951988293","message":"test"},"appId":"189610","operationType":"ADD"}
-
-
     }
     }
 
 
     @Test
     @Test

+ 61 - 0
src/test/java/com/izouma/wenlvju/web/TrainingInstitutionControllerTest.java

@@ -0,0 +1,61 @@
+package com.izouma.wenlvju.web;
+
+
+import com.izouma.wenlvju.ApplicationTests;
+import com.izouma.wenlvju.converter.StringArrayConverter;
+import com.izouma.wenlvju.domain.TrainingInstitution;
+import com.izouma.wenlvju.dto.PageQuery;
+import com.izouma.wenlvju.repo.TrainingInstitutionRepo;
+import com.izouma.wenlvju.service.TrainingInstitutionService;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TrainingInstitutionControllerTest extends ApplicationTests {
+
+    @Autowired
+    private TrainingInstitutionController trainingInstitutionController;
+
+    @Autowired
+    private TrainingInstitutionService trainingInstitutionService;
+
+    @Autowired
+    private TrainingInstitutionRepo trainingInstitutionRepo;
+
+    @Test
+    public void test() throws InterruptedException {
+        long count = trainingInstitutionRepo.count();
+
+        PageQuery pageQuery = new PageQuery();
+        pageQuery.setSize(1000);
+        for (int i = 5; i < count / 1000; i++) {
+            pageQuery.setPage(i);
+            List<TrainingInstitution> content = trainingInstitutionController.all(pageQuery).getContent();
+            List<TrainingInstitution> result = new ArrayList<>();
+            content.forEach(t -> {
+                if (t.getPhone() != null && (t.getPhone().length() < 11 || t.getPhone().contains("-"))) {
+                    t.setPhone(null);
+                    result.add(t);
+                }
+
+            });
+            trainingInstitutionRepo.saveAll(result);
+            System.out.println(i);
+//            Thread.sleep(5 * 60 * 1000);
+//            Thread.sleep(30 * 1000);
+        }
+
+//        System.out.println("12".split(","));
+    }
+
+    @Test
+    public void test1() throws InterruptedException {
+        List<String> phones = trainingInstitutionRepo.findAllBySubmitFalseAndPhoneIsNotNull();
+        trainingInstitutionService.batchSend(phones);
+
+    }
+
+
+}

Некоторые файлы не были показаны из-за большого количества измененных файлов