Procházet zdrojové kódy

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

panhui před 5 roky
rodič
revize
d070b6df1a
28 změnil soubory, kde provedl 783 přidání a 66 odebrání
  1. 24 0
      src/main/java/com/izouma/wenlvju/converter/ExpertConverter.java
  2. 1 0
      src/main/java/com/izouma/wenlvju/domain/GradingOrganization.java
  3. 6 2
      src/main/java/com/izouma/wenlvju/domain/Organization.java
  4. 6 3
      src/main/java/com/izouma/wenlvju/domain/Rate.java
  5. 6 0
      src/main/java/com/izouma/wenlvju/domain/Setting.java
  6. 5 0
      src/main/java/com/izouma/wenlvju/domain/User.java
  7. 10 0
      src/main/java/com/izouma/wenlvju/dto/Expert.java
  8. 10 0
      src/main/java/com/izouma/wenlvju/dto/ExpertDTO.java
  9. 7 1
      src/main/java/com/izouma/wenlvju/dto/OrganizationRegDTO.java
  10. 4 0
      src/main/java/com/izouma/wenlvju/enums/RateStatus.java
  11. 3 0
      src/main/java/com/izouma/wenlvju/repo/OrganizationRepo.java
  12. 6 0
      src/main/java/com/izouma/wenlvju/repo/SettingRepo.java
  13. 12 5
      src/main/java/com/izouma/wenlvju/service/ArtTypeService.java
  14. 22 1
      src/main/java/com/izouma/wenlvju/service/RateExpertAuditService.java
  15. 29 0
      src/main/java/com/izouma/wenlvju/service/SettingService.java
  16. 6 1
      src/main/java/com/izouma/wenlvju/service/UserService.java
  17. 0 1
      src/main/java/com/izouma/wenlvju/web/RateExpertAuditController.java
  18. 15 1
      src/main/java/com/izouma/wenlvju/web/SettingController.java
  19. 1 0
      src/main/vue/src/mixins/rateStatus.js
  20. 3 3
      src/main/vue/src/router.js
  21. 3 3
      src/main/vue/src/views/ArtTypes.vue
  22. 37 7
      src/main/vue/src/views/ExpertEdit.vue
  23. 3 2
      src/main/vue/src/views/ExpertList.vue
  24. 29 8
      src/main/vue/src/views/Login.vue
  25. 3 2
      src/main/vue/src/views/RateList.vue
  26. 381 0
      src/main/vue/src/views/Settings.vue
  27. 38 23
      src/main/vue/src/views/organization/OrganizationInfo.vue
  28. 113 3
      src/main/vue/src/views/organization/RateEdit.vue

+ 24 - 0
src/main/java/com/izouma/wenlvju/converter/ExpertConverter.java

@@ -0,0 +1,24 @@
+package com.izouma.wenlvju.converter;
+
+import com.alibaba.fastjson.JSON;
+import com.izouma.wenlvju.dto.Expert;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.persistence.AttributeConverter;
+
+public class ExpertConverter implements AttributeConverter<Expert, String> {
+    @Override
+    public String convertToDatabaseColumn(Expert fileObject) {
+        if (fileObject != null  )
+            return JSON.toJSONString(fileObject);
+        return null;
+    }
+
+    @Override
+    public Expert convertToEntityAttribute(String s) {
+        if (StringUtils.isNotEmpty(s)) {
+            return JSON.parseObject(s, Expert.class);
+        }
+        return null;
+    }
+}

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

@@ -20,4 +20,5 @@ public class GradingOrganization extends BaseEntity {
     private String code;
 
     private String name;
+
 }

+ 6 - 2
src/main/java/com/izouma/wenlvju/domain/Organization.java

@@ -27,7 +27,7 @@ public class Organization extends BaseEntity {
     private String name;
 
     @ApiModelProperty(value = "考级机构名称")
-    private String examinationAgency;
+    private Long gradingOrganizationId;
 
     @ApiModelProperty(value = "统一社会信用代码")
     private String uscc;
@@ -53,9 +53,13 @@ public class Organization extends BaseEntity {
     private String privacyPolicy;
 
     @ApiModelProperty(value = "证件号码")
-    private String IDNo;
+    private String idNo;
 
     @ApiModelProperty(value = "经营范围")
     private String businessScope;
 
+    private int sort;
+
+    private String code;
+
 }

+ 6 - 3
src/main/java/com/izouma/wenlvju/domain/Rate.java

@@ -63,9 +63,6 @@ public class Rate extends BaseEntity {
     @ApiModelProperty(value = "是否提交")
     private boolean submit;
 
-//    @Convert(converter = StringArrayConverter.class)
-//    private List<String> img;
-
     @NonNull
     @ApiModelProperty(value = "承办单位")
     private Long organizationId;
@@ -154,4 +151,10 @@ public class Rate extends BaseEntity {
     @Column(columnDefinition = "TEXT")
     @Convert(converter = ReviewTimeListConverter.class)
     private List<ReviewTime> reviewTimes = new ArrayList<>();
+
+    @Column(columnDefinition = "TEXT")
+    @Convert(converter = StringArrayConverter.class)
+    private List<String> img;
+
+    private String remark;
 }

+ 6 - 0
src/main/java/com/izouma/wenlvju/domain/Setting.java

@@ -8,6 +8,9 @@ import lombok.NoArgsConstructor;
 import org.hibernate.annotations.Where;
 
 import javax.persistence.Entity;
+import javax.persistence.Transient;
+import java.util.ArrayList;
+import java.util.List;
 
 @Data
 @AllArgsConstructor
@@ -24,4 +27,7 @@ public class Setting extends BaseEntity {
     private String code;
 
     private int flag;
+
+    @Transient
+    private List<Setting> children = new ArrayList<>();
 }

+ 5 - 0
src/main/java/com/izouma/wenlvju/domain/User.java

@@ -4,6 +4,8 @@ import com.alibaba.excel.annotation.ExcelIgnore;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.izouma.wenlvju.annotations.Searchable;
 import com.izouma.wenlvju.config.Constants;
+import com.izouma.wenlvju.converter.ExpertConverter;
+import com.izouma.wenlvju.dto.Expert;
 import com.izouma.wenlvju.security.Authority;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -76,4 +78,7 @@ public class User extends BaseEntity implements Serializable {
 
     @ApiModelProperty(value = "艺术分类id")
     private Long artTypeId;
+
+    @Convert(converter = ExpertConverter.class)
+    private Expert expert;
 }

+ 10 - 0
src/main/java/com/izouma/wenlvju/dto/Expert.java

@@ -0,0 +1,10 @@
+package com.izouma.wenlvju.dto;
+
+import lombok.Data;
+
+@Data
+public class Expert {
+    private String work;
+
+    private String position;
+}

+ 10 - 0
src/main/java/com/izouma/wenlvju/dto/ExpertDTO.java

@@ -1,6 +1,7 @@
 package com.izouma.wenlvju.dto;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.izouma.wenlvju.domain.User;
 import io.swagger.annotations.ApiModel;
 import lombok.AllArgsConstructor;
@@ -29,10 +30,19 @@ public class ExpertDTO {
 
     private Long artTypeId;
 
+    private String work;
+
+    private String position;
+
     private String artType;
 
     public ExpertDTO(User user, String artType) {
         BeanUtil.copyProperties(user, this);
+        Expert expert = user.getExpert();
+        if (ObjectUtil.isNotNull(expert)){
+            this.work = expert.getWork();
+            this.position = expert.getPosition();
+        }
         this.artType = artType;
     }
 }

+ 7 - 1
src/main/java/com/izouma/wenlvju/dto/OrganizationRegDTO.java

@@ -19,6 +19,8 @@ public class OrganizationRegDTO {
 
     private String password;
 
+    private String password1;
+
     private String phone;
 
     private String email;
@@ -29,7 +31,11 @@ public class OrganizationRegDTO {
 
     private String district;
 
-    private String examinationAgency;
+    private String districtCode;
+
+    private Long gradingOrganizationId;
+
+    private Long gradingCode;
 //    private List<String> district1;
 
 }

+ 4 - 0
src/main/java/com/izouma/wenlvju/enums/RateStatus.java

@@ -18,6 +18,10 @@ public enum RateStatus {
      */
     ASSIGN_EXPERT,
     /*
+    确定审查时间
+     */
+    REVIEW_TIME,
+    /*
     待专家组考察(分配专家组)
      */
     REVIEW_PENDING,

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

@@ -16,4 +16,7 @@ public interface OrganizationRepo extends JpaRepository<Organization, Long>, Jpa
     void softDelete(Long id);
 
     Optional<Organization> findByUserId(Long userId);
+
+    @Query(nativeQuery = true, value = "SELECT ifnull(max(sort + 1),1) FROM organization")
+    int nextSort();
 }

+ 6 - 0
src/main/java/com/izouma/wenlvju/repo/SettingRepo.java

@@ -7,10 +7,16 @@ import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 
 import javax.transaction.Transactional;
+import java.util.List;
 
 public interface SettingRepo extends JpaRepository<Setting, Long>, JpaSpecificationExecutor<Setting> {
     @Query("update Setting t set t.del = true where t.id = ?1")
     @Modifying
     @Transactional
     void softDelete(Long id);
+
+    @Query(nativeQuery = true, value = "SELECT ifnull(max(flag + 1),1) FROM setting")
+    int nextSort();
+
+    List<Setting> findAllByFlag(int flag);
 }

+ 12 - 5
src/main/java/com/izouma/wenlvju/service/ArtTypeService.java

@@ -2,6 +2,7 @@ package com.izouma.wenlvju.service;
 
 import com.alibaba.fastjson.JSON;
 import com.izouma.wenlvju.domain.ArtType;
+import com.izouma.wenlvju.domain.Menu;
 import com.izouma.wenlvju.dto.ArtTypeDTO;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.repo.ArtTypeRepo;
@@ -10,10 +11,7 @@ import lombok.AllArgsConstructor;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
@@ -39,7 +37,6 @@ public class ArtTypeService {
     public List<ArtType> getTree(List<?> list1) {
         String s = JSON.toJSONString(list1);
         List<ArtType> list = JSON.parseArray(s, ArtType.class);
-
         Map<Long, ArtType> dtoMap = new HashMap<>();
         for (ArtType node : list) {
             dtoMap.put(node.getId(), node);
@@ -58,6 +55,16 @@ public class ArtTypeService {
                 }
             }
         }
+        sortMenu(resultList);
         return resultList;
     }
+
+    private void sortMenu(List<ArtType> menus) {
+        menus.sort(Comparator.comparing(ArtType::getCode));
+        for (ArtType menu : menus) {
+            if (menu.getChildren() != null) {
+                sortMenu(menu.getChildren());
+            }
+        }
+    }
 }

+ 22 - 1
src/main/java/com/izouma/wenlvju/service/RateExpertAuditService.java

@@ -1,10 +1,14 @@
 package com.izouma.wenlvju.service;
 
 import cn.hutool.core.util.ObjectUtil;
+import com.izouma.wenlvju.domain.GradeRule;
+import com.izouma.wenlvju.domain.Rate;
 import com.izouma.wenlvju.domain.RateExpertAudit;
 import com.izouma.wenlvju.dto.PageQuery;
+import com.izouma.wenlvju.enums.OrganizationGrade;
 import com.izouma.wenlvju.exception.BusinessException;
 import com.izouma.wenlvju.repo.RateExpertAuditRepo;
+import com.izouma.wenlvju.repo.RateRepo;
 import com.izouma.wenlvju.utils.JpaUtils;
 import com.izouma.wenlvju.utils.ObjUtils;
 import lombok.AllArgsConstructor;
@@ -17,7 +21,8 @@ import java.util.List;
 @AllArgsConstructor
 public class RateExpertAuditService {
 
-    private RateExpertAuditRepo rateExpertAuditRepo;
+    private final RateExpertAuditRepo rateExpertAuditRepo;
+    private final RateRepo            rateRepo;
 
     public Page<RateExpertAudit> all(PageQuery pageQuery) {
         return rateExpertAuditRepo.findAll(JpaUtils.toSpecification(pageQuery, RateExpertAudit.class), JpaUtils.toPageRequest(pageQuery));
@@ -42,4 +47,20 @@ public class RateExpertAuditService {
             }
         });
     }
+
+    public void grade(Long rateId) {
+        List<RateExpertAudit> audits = rateExpertAuditRepo.findAllByRateId(rateId);
+        int sum = audits.stream().mapToInt(RateExpertAudit::getScore).sum();
+        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.setGrade(grade);
+        rateRepo.save(rate);
+    }
 }

+ 29 - 0
src/main/java/com/izouma/wenlvju/service/SettingService.java

@@ -1,5 +1,7 @@
 package com.izouma.wenlvju.service;
 
+import com.alibaba.fastjson.JSON;
+import com.izouma.wenlvju.domain.ArtType;
 import com.izouma.wenlvju.domain.Setting;
 import com.izouma.wenlvju.dto.PageQuery;
 import com.izouma.wenlvju.repo.SettingRepo;
@@ -8,6 +10,8 @@ import lombok.AllArgsConstructor;
 import org.springframework.data.domain.Page;
 import org.springframework.stereotype.Service;
 
+import java.util.*;
+
 @Service
 @AllArgsConstructor
 public class SettingService {
@@ -17,4 +21,29 @@ public class SettingService {
     public Page<Setting> all(PageQuery pageQuery) {
         return settingRepo.findAll(JpaUtils.toSpecification(pageQuery, Setting.class), JpaUtils.toPageRequest(pageQuery));
     }
+
+    public List<Setting> getTree(List<?> list1) {
+        String s = JSON.toJSONString(list1);
+        List<Setting> list = JSON.parseArray(s, Setting.class);
+        Map<Long, Setting> dtoMap = new HashMap<>();
+        for (Setting node : list) {
+            dtoMap.put(node.getId(), node);
+        }
+
+        List<Setting> resultList = new ArrayList<>();
+        for (Map.Entry<Long, Setting> entry : dtoMap.entrySet()) {
+            Setting node = entry.getValue();
+            if (node.getParent() == null) {
+                // 如果是顶层节点,直接添加到结果集合中
+                resultList.add(node);
+            } else {
+                // 如果不是顶层节点,找其父节点,并且添加到父节点的子节点集合中
+                if (dtoMap.get(node.getParent()) != null) {
+                    dtoMap.get(node.getParent()).getChildren().add(node);
+                }
+            }
+        }
+        return resultList;
+    }
+
 }

+ 6 - 1
src/main/java/com/izouma/wenlvju/service/UserService.java

@@ -232,6 +232,9 @@ public class UserService {
         user.setAuthorities(Collections.singleton(Authority.get(AuthorityName.ROLE_ORGANIZER)));
         User save = userRepo.save(user);
 
+        int sort = organizationRepo.nextSort();
+        String code = dto.getDistrictCode() + dto.getGradingCode() + String.format("%04d",sort);
+
         organizationRepo.save(
                 Organization.builder()
                         .businessLicense(dto.getBusinessLicense())
@@ -239,7 +242,9 @@ public class UserService {
                         .name(dto.getOrganizationName())
 //                        .district1(dto.getDistrict1())
                         .district(dto.getDistrict())
-                        .examinationAgency(dto.getExaminationAgency())
+                        .gradingOrganizationId(dto.getGradingOrganizationId())
+                        .sort(sort)
+                        .code(code)
                         .build());
 
         return user;

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

@@ -1,7 +1,6 @@
 package com.izouma.wenlvju.web;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.izouma.wenlvju.domain.RateExpertAudit;
 import com.izouma.wenlvju.service.RateExpertAuditService;

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

@@ -1,4 +1,5 @@
 package com.izouma.wenlvju.web;
+
 import com.izouma.wenlvju.domain.Setting;
 import com.izouma.wenlvju.service.SettingService;
 import com.izouma.wenlvju.dto.PageQuery;
@@ -20,7 +21,7 @@ import java.util.List;
 @AllArgsConstructor
 public class SettingController extends BaseController {
     private SettingService settingService;
-    private SettingRepo settingRepo;
+    private SettingRepo    settingRepo;
 
     //@PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/save")
@@ -30,6 +31,9 @@ public class SettingController extends BaseController {
             ObjUtils.merge(orig, record);
             return settingRepo.save(orig);
         }
+        if (record.getParent() == null) {
+            record.setFlag(settingRepo.nextSort());
+        }
         return settingRepo.save(record);
     }
 
@@ -56,5 +60,15 @@ public class SettingController extends BaseController {
         List<Setting> data = all(pageQuery).getContent();
         ExcelUtils.export(response, data);
     }
+
+    @PostMapping("/allList")
+    public List<Setting> allList() {
+        return settingService.getTree(settingRepo.findAll());
+    }
+
+    @PostMapping("/byFlag")
+    public List<Setting> byFlag(int flag) {
+        return settingService.getTree(settingRepo.findAllByFlag(flag));
+    }
 }
 

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

@@ -6,6 +6,7 @@ export default {
                 { label: '等待初审', value: 'FIRST_REVIEW_PENDING' },
                 { label: '初审驳回', value: 'FIRST_REVIEW_DENY' },
                 { label: '已上报', value: 'ASSIGN_EXPERT' },
+                { label: '待确定审查时间', value: 'REVIEW_TIME' },
                 { label: '待专家组考察', value: 'REVIEW_PENDING' },
                 { label: '最终评审', value: 'SUBMIT_GRADE' },
                 { label: '待提交纸质材料', value: 'SUBMIT_PAPER_MATERIALS' },

+ 3 - 3
src/main/vue/src/router.js

@@ -408,9 +408,9 @@ const router = new Router({
                     }
                 },
                 {
-                    path: '/settingList',
-                    name: 'SettingList',
-                    component: () => import(/* webpackChunkName: "settingList" */ '@/views/SettingList.vue'),
+                    path: '/settings',
+                    name: 'Settings',
+                    component: () => import(/* webpackChunkName: "settingList" */ '@/views/Settings.vue'),
                     meta: {
                         title: '设置'
                     }

+ 3 - 3
src/main/vue/src/views/ArtTypes.vue

@@ -49,9 +49,9 @@
 export default {
     created() {
         this.getData();
-        this.$http.get('/authority/all').then(res => {
-            this.authorities = res;
-        });
+        // this.$http.get('/authority/all').then(res => {
+        //     this.authorities = res;
+        // });
     },
     data() {
         return {

+ 37 - 7
src/main/vue/src/views/ExpertEdit.vue

@@ -17,9 +17,9 @@
             <el-form-item prop="nickname" label="姓名">
                 <el-input v-model="formData.nickname"></el-input>
             </el-form-item>
-            <el-form-item prop="age" label="年龄">
+            <!-- <el-form-item prop="age" label="年龄">
                 <el-input v-model="formData.age"></el-input>
-            </el-form-item>
+            </el-form-item> -->
             <el-form-item v-if="formData.id" label="密码">
                 <el-button type="primary" plain @click="resetPassword" size="mini">重置 </el-button>
             </el-form-item>
@@ -29,14 +29,28 @@
             <el-form-item prop="phone" label="手机">
                 <el-input v-model="formData.phone"></el-input>
             </el-form-item>
-            <el-form-item prop="artTypeId" label="艺术分类">
+            <el-form-item prop="expert" label="单位">
+                <!-- <el-input v-model="formData.expert.work"></el-input> -->
+                <el-select v-model="expert.work" style="width: 100%" placeholder="请选择单位" filterable>
+                    <el-option
+                        v-for="item in settings"
+                        :key="item.id"
+                        :label="item.name"
+                        :value="item.name"
+                    ></el-option>
+                </el-select>
+            </el-form-item>
+            <el-form-item prop="expert" label="职称">
+                <el-input v-model="expert.position"></el-input>
+            </el-form-item>
+            <el-form-item prop="artTypeId" label="专业">
                 <el-cascader
                     style="width: 100%"
                     v-model="formData.artTypeId"
                     :props="optionProps"
                     :options="artTypes"
                     :show-all-levels="false"
-                    placeholder="请选择艺术分类"
+                    placeholder="请选择专业"
                 >
                 </el-cascader>
             </el-form-item>
@@ -71,6 +85,7 @@ export default {
                 .get(`/user/get/${this.$route.query.id}`)
                 .then(res => {
                     this.formData = res;
+                    this.expert = res.expert;
                 })
                 .catch(e => {
                     console.log(e);
@@ -94,6 +109,14 @@ export default {
             .catch(e => {
                 console.log(e);
             });
+        this.$http
+            .post('/setting/byFlag', { flag: 1 })
+            .then(res => {
+                this.settings = res[0].children;
+            })
+            .catch(e => {
+                console.log(e);
+            });
     },
     data() {
         return {
@@ -102,6 +125,10 @@ export default {
                 avatar: 'https://zhumj.oss-cn-hangzhou.aliyuncs.com/image/user.jpg',
                 authorities: [{ name: 'ROLE_EXPERT' }]
             },
+            expert: {
+                work: '',
+                position: ''
+            },
             rules: {
                 // avatar: [
                 //     {
@@ -113,7 +140,7 @@ export default {
                 // ],
                 username: [{ required: true, message: '请输入昵称', trigger: 'blur' }],
                 nickname: [{ required: true, message: '请输入昵称', trigger: 'blur' }],
-                password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
+                // password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
                 phone: [
                     {
                         required: true,
@@ -122,7 +149,8 @@ export default {
                         trigger: 'blur'
                     }
                 ],
-                authorities: [{ required: true, message: '请选择角色', trigger: 'blur' }]
+                authorities: [{ required: true, message: '请选择角色', trigger: 'blur' }],
+                artTypeId: [{ required: true, message: '请选择专业', trigger: 'blur' }]
             },
             authorities: [],
             districts: [],
@@ -135,7 +163,8 @@ export default {
                 checkStrictly: true,
                 expandTrigger: 'hover'
             },
-            artTypes: []
+            artTypes: [],
+            settings: []
         };
     },
     methods: {
@@ -150,6 +179,7 @@ export default {
         },
         submit() {
             this.formData.username = this.formData.phone;
+            this.formData.expert = this.expert;
             this.$http
                 .post(this.formData.id ? '/user/save' : '/user/create', this.formData, { body: 'json' })
                 .then(res => {

+ 3 - 2
src/main/vue/src/views/ExpertList.vue

@@ -27,9 +27,10 @@
             <!-- <el-table-column prop="id" label="ID" width="100"> </el-table-column> -->
             <!-- <el-table-column prop="username" label="用户名" min-width="300"> </el-table-column> -->
             <el-table-column prop="nickname" label="姓名"> </el-table-column>
-            <el-table-column prop="age" label="年龄"></el-table-column>
             <el-table-column prop="phone" label="手机号"></el-table-column>
-            <el-table-column prop="artType" label="艺术分类"></el-table-column>
+            <el-table-column prop="artType" label="专业"></el-table-column>
+            <el-table-column prop="work" label="单位"></el-table-column>
+            <el-table-column prop="position" label="职称"></el-table-column>
             <!-- <el-table-column label="头像" min-width="300">
                 <template slot-scope="{ row }">
                     <el-image

+ 29 - 8
src/main/vue/src/views/Login.vue

@@ -77,14 +77,15 @@
                         <el-input class="input-width" v-model="registerInfo.email" placeholder="电子邮箱"> </el-input>
                     </el-form-item>
                     <el-form-item
-                        prop="examinationAgency"
+                        prop="gradingOrganizationId"
                         label="所属考级机构"
                         :rules="{ required: true, message: '请选择所属考级机构', trigger: 'blur' }"
                     >
                         <el-select
-                            v-model="registerInfo.examinationAgency"
+                            v-model="registerInfo.gradingOrganizationId"
                             placeholder="请选择所属考级机构"
                             style="width: 350px"
+                            @change="setGradingCode"
                         >
                             <el-option
                                 v-for="(item, index) in examination"
@@ -101,12 +102,17 @@
                         :rules="{ required: true, message: '请选择注册地址', trigger: 'blur' }"
                     >
                         <!-- <district-choose v-model="registerInfo.district"></district-choose> -->
-                        <el-select v-model="registerInfo.district" placeholder="请选择注册地址" style="width: 350px">
+                        <el-select
+                            v-model="registerInfo.district"
+                            placeholder="请选择注册地址"
+                            style="width: 350px"
+                            @change="setDistrictCode"
+                        >
                             <el-option
                                 v-for="(item, index) in districtOptions"
                                 :key="index"
                                 :value="item.label"
-                                :label="item.value"
+                                :label="item.label"
                             ></el-option>
                         </el-select>
                     </el-form-item>
@@ -217,7 +223,6 @@ export default {
             userInfo: {
                 username: '',
                 password: '',
-                password1: '',
                 phone: '',
                 code: ''
             },
@@ -226,7 +231,8 @@ export default {
                 username: '',
                 password: '',
                 password1: '',
-                businessLicense: ''
+                businessLicense: '',
+                districtCode: ''
             },
             activeName: 'first',
             time: 0,
@@ -266,7 +272,7 @@ export default {
                     res.forEach(item => {
                         this.districtOptions.push({
                             label: item.name,
-                            value: item.name
+                            value: item.id
                         });
                     });
                 }
@@ -282,7 +288,8 @@ export default {
                     res.content.forEach(item => {
                         this.examination.push({
                             label: item.name,
-                            value: item.id
+                            value: item.id,
+                            code: item.code
                         });
                     });
                 }
@@ -406,6 +413,20 @@ export default {
                     clearInterval(i);
                 }
             }, 1000);
+        },
+        setDistrictCode(res) {
+            let data = this.districtOptions.find(item => {
+                return item.label == res;
+            });
+            this.registerInfo.districtCode = data.value;
+        },
+        setGradingCode(res) {
+            console.log(res);
+            let data = this.examination.find(item => {
+                return item.value == res;
+            });
+            console.log(data);
+            this.registerInfo.gradingCode = data.code;
         }
     }
 };

+ 3 - 2
src/main/vue/src/views/RateList.vue

@@ -29,6 +29,7 @@
             <el-table-column prop="createdAt" label="申请时间" min-width="100"></el-table-column>
             <el-table-column prop="year" label="年度" min-width="60"> </el-table-column>
             <el-table-column prop="status" label="状态" :formatter="statusFormatter" min-width="100"> </el-table-column>
+            <el-table-column label="考级机构"></el-table-column>
             <el-table-column prop="score" label="分数">
                 <template slot-scope="{ row }">
                     <span v-if="row.score">{{ row.score }}</span>
@@ -65,9 +66,9 @@
                     >
                         退回
                     </el-button>
-                    <el-button v-if="row.status === 'SUBMIT_GRADE'" @click="openScore(row)" type="warning" plain
+                    <!-- <el-button v-if="row.status === 'SUBMIT_GRADE'" @click="openScore(row)" type="warning" plain
                         >填写分数</el-button
-                    >
+                    > -->
                     <el-button
                         @click="supervision(row.id)"
                         type="success"

+ 381 - 0
src/main/vue/src/views/Settings.vue

@@ -0,0 +1,381 @@
+<template>
+    <div>
+        <el-row :gutter="20">
+            <el-col :span="12">
+                <div class="menu-tree">
+                    <el-tree
+                        :data="menus"
+                        :render-content="renderContent"
+                        :highlight-current="true"
+                        :expand-on-click-node="true"
+                        node-key="id"
+                        v-loading="loading"
+                        accordion
+                        @node-click="nodeClick"
+                        :default-expanded-keys="expandKeys"
+                        :default-checked-keys="expandKeys"
+                    >
+                    </el-tree>
+                    <el-button type="text" @click="addRootMenu" style="margin-left: 24px;">添加 </el-button>
+                </div>
+            </el-col>
+            <transition name="el-fade-in">
+                <el-col :span="12" v-if="dialogVisible">
+                    <div class="menu-tree">
+                        <div style="font-weight:bold;padding:10px 0">{{ menu.id ? '编辑' : '新增' }}</div>
+                        <el-form :model="menu" ref="form" label-position="top">
+                            <el-form-item
+                                label="名称"
+                                prop="name"
+                                :rules="[{ required: true, message: '请填写名称', trigger: 'blur' }]"
+                            >
+                                <el-input v-model="menu.name"></el-input>
+                            </el-form-item>
+                            <el-form-item label="代码" prop="code">
+                                <el-input v-model="menu.code"></el-input>
+                            </el-form-item>
+                        </el-form>
+                        <div slot="footer">
+                            <el-button @click="dialogVisible = false">取消 </el-button>
+                            <el-button type="primary" @click="addMenu" :loading="loading">保存 </el-button>
+                        </div>
+                    </div>
+                </el-col>
+            </transition>
+        </el-row>
+    </div>
+</template>
+<script>
+export default {
+    created() {
+        this.getData();
+    },
+    data() {
+        return {
+            dialogVisible: false,
+            curr: null,
+            loading: false,
+            menus: [],
+            menu: {
+                name: '',
+                code: ''
+            },
+            parent: null,
+            currentRef: null,
+            edit: false,
+            expandKeys: [],
+            authorities: []
+        };
+    },
+    methods: {
+        addRootMenu() {
+            this.menu = {
+                name: '',
+                code: ''
+                // authorities: [{ name: 'ROLE_ADMIN' }]
+            };
+            this.parent = null;
+            this.icon = 'bars';
+            this.dialogVisible = true;
+            setTimeout(() => {
+                this.showIcon('bars');
+            }, 100);
+        },
+        showAddDialog(node, data) {
+            this.edit = false;
+            this.parent = node.data;
+            this.menu = {
+                parent: node.data.id,
+                flag: node.data.flag,
+                name: '',
+                code: ''
+                // authorities: [{ name: 'ROLE_ADMIN' }]
+            };
+            this.dialogVisible = true;
+        },
+        showEditDialog(node, data) {
+            this.edit = true;
+            this.currentRef = node.data;
+            this.menu = {
+                ...data
+            };
+            this.dialogVisible = true;
+        },
+        addMenu() {
+            this.$refs.form.validate(valid => {
+                if (valid) {
+                    this.loading = true;
+                    let menu = { ...this.menu };
+                    delete menu.children;
+                    this.$http
+                        .post('/setting/save', menu, { body: 'json' })
+                        .then(res => {
+                            this.loading = false;
+                            this.$message.success('添加成功');
+                            this.dialogVisible = false;
+                            this.getData();
+                        })
+                        .catch(e => {
+                            console.log(e);
+                            this.loading = false;
+                            this.$message.error(e.error);
+                        });
+                }
+            });
+        },
+        remove(node, data) {
+            console.log(node);
+            this.$confirm('确定删除菜单?', '提示', {
+                confirmButtonText: '确定',
+                cancelButtonText: '取消',
+                type: 'error'
+            })
+                .then(() => {
+                    return this.$http.post(
+                        '/setting/save',
+                        {
+                            ...data,
+                            active: false,
+                            children: null
+                        },
+                        { body: 'json' }
+                    );
+                })
+                .then(res => {
+                    this.$message.success('删除成功');
+                    this.getData();
+                })
+                .catch(e => {
+                    this.loading = false;
+                    if (e !== 'cancel') {
+                        console.log(e);
+                        this.$message.error(e.error);
+                    }
+                });
+        },
+        moveUp(node, data) {
+            if (node.previousSibling) {
+                this.loading = true;
+                let sort0 = node.previousSibling.data.sort,
+                    sort1 = node.data.sort;
+                Promise.all([
+                    this.$http.post(
+                        '/setting/save',
+                        {
+                            ...node.data,
+                            children: null,
+                            sort: sort0
+                        },
+                        { body: 'json' }
+                    ),
+                    this.$http.post(
+                        '/setting/save',
+                        {
+                            ...node.previousSibling.data,
+                            children: null,
+                            sort: sort1
+                        },
+                        { body: 'json' }
+                    )
+                ])
+                    .then(_ => {
+                        this.loading = false;
+                        this.getData();
+                    })
+                    .catch(e => {
+                        console.log(e);
+                        this.loading = false;
+                        this.$message.error(e.error);
+                    });
+            }
+        },
+        moveDown(node, data) {
+            if (node.nextSibling) {
+                this.loading = true;
+                let sort0 = node.data.sort,
+                    sort1 = node.nextSibling.data.sort;
+                Promise.all([
+                    this.$http.post(
+                        '/setting/save',
+                        {
+                            ...node.data,
+                            children: null,
+                            sort: sort1
+                        },
+                        { body: 'json' }
+                    ),
+                    this.$http.post(
+                        '/setting/save',
+                        {
+                            ...node.nextSibling.data,
+                            children: null,
+                            sort: sort0
+                        },
+                        { body: 'json' }
+                    )
+                ])
+                    .then(_ => {
+                        this.loading = false;
+                        this.getData();
+                    })
+                    .catch(e => {
+                        console.log(e);
+                        this.loading = false;
+                        this.$message.error(e.error);
+                    });
+            }
+        },
+        getData() {
+            this.$http
+                .post('/setting/allList')
+                .then(res => {
+                    this.menus = res;
+                })
+                .catch(e => {
+                    console.log(e);
+                    this.$message.error(e.error);
+                });
+        },
+        renderContent(h, { node, data, store }) {
+            return (
+                <span
+                    class={
+                        this.menu.id == data.id || (this.menu.parent == data.id && !this.menu.id)
+                            ? 'custom-tree-node selected'
+                            : 'custom-tree-node'
+                    }
+                >
+                    <span>{data.name}</span>
+                    <span class="url">{data.code}</span>
+                    <span class="opt">
+                        <el-button
+                            type="text"
+                            on-click={e => {
+                                this.showEditDialog(node, data), e.stopPropagation();
+                            }}
+                            icon="el-icon-edit"
+                        >
+                            编辑
+                        </el-button>
+                        <el-button
+                            type="text"
+                            on-click={e => {
+                                this.showAddDialog(node, data), e.stopPropagation();
+                            }}
+                            icon="el-icon-plus"
+                        >
+                            添加
+                        </el-button>
+                        <el-button
+                            type="text"
+                            on-click={e => {
+                                this.remove(node, data), e.stopPropagation();
+                            }}
+                            icon="el-icon-delete"
+                        >
+                            删除
+                        </el-button>
+                    </span>
+                </span>
+            );
+        },
+        showIcon(val) {
+            if (!this.$refs.iconContainer) return;
+            if (FontAwesome.icon({ prefix: 'fas', iconName: val })) {
+                this.$refs.iconContainer.innerHTML = '';
+                let i = document.createElement('i');
+                i.className = 'fas fa-' + val;
+                this.$refs.iconContainer.append(i);
+                FontAwesome.dom.i2svg();
+                this.menu.icon = 'fas fa-' + val;
+            } else if (FontAwesome.icon({ prefix: 'fab', iconName: val })) {
+                this.$refs.iconContainer.innerHTML = '';
+                let i = document.createElement('i');
+                i.className = 'fab fa-' + val;
+                this.$refs.iconContainer.append(i);
+                FontAwesome.dom.i2svg();
+                this.menu.icon = 'fab fa-' + val;
+            } else {
+                this.$refs.iconContainer.innerHTML = '';
+                let i = document.createElement('i');
+                i.className = 'fab fa-' + val;
+                this.$refs.iconContainer.append(i);
+                FontAwesome.dom.i2svg();
+                this.menu.icon = '';
+            }
+        },
+        nodeClick(data, node, el) {
+            if (this.expandKeys[0] != data.id) {
+                this.expandKeys = [data.id];
+            }
+        }
+    },
+    watch: {
+        icon(val) {
+            this.showIcon(val);
+        },
+        category() {
+            this.getData();
+        }
+    }
+};
+</script>
+<style lang="less" scoped>
+.menu-tree {
+    border-radius: 4px;
+    background: white;
+    margin-top: 20px;
+    padding: 10px;
+}
+</style>
+<style lang="less">
+.menu-tree {
+    .el-tree-node__content {
+        height: 40px;
+        line-height: 40px;
+    }
+}
+.custom-tree-node {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    font-size: 14px;
+    padding-right: 8px;
+    line-height: 40px;
+    height: 40px;
+    .url {
+        flex-grow: 1;
+        text-align: right;
+        margin-right: 20px;
+        color: #999;
+    }
+    .opt {
+        opacity: 0;
+    }
+    &.selected {
+        border: 2px solid #409eff;
+        border-radius: 4px;
+        padding: 0 10px;
+        box-sizing: border-box;
+        .opt {
+            opacity: 1;
+        }
+    }
+}
+
+.custom-tree-node:hover {
+    .opt {
+        opacity: 1;
+    }
+}
+
+.available-icons {
+    color: #409eff;
+    text-decoration: none;
+    &:hover {
+        color: #409eff;
+        text-decoration: none;
+    }
+}
+</style>

+ 38 - 23
src/main/vue/src/views/organization/OrganizationInfo.vue

@@ -20,8 +20,8 @@
                         <el-option
                             v-for="(item, index) in examination"
                             :key="index"
-                            :value="item"
-                            :label="item"
+                            :value="item.value"
+                            :label="item.label"
                         ></el-option>
                     </el-select>
                 </el-form-item>
@@ -49,8 +49,8 @@
                 <el-form-item label="法人姓名" prop="privacyPolicy">
                     <el-input v-model="formData.privacyPolicy" placeholder="请输入法人姓名"></el-input>
                 </el-form-item>
-                <el-form-item label="证件号码" prop="IDNo">
-                    <el-input v-model="formData.IDNo" placeholder="请输入证件号码"></el-input>
+                <el-form-item label="证件号码" prop="idNo">
+                    <el-input v-model="formData.idNo" placeholder="请输入证件号码"></el-input>
                 </el-form-item>
                 <el-form-item label="地址" prop="district" class="address">
                     <el-select v-model="formData.district" style="width:100%">
@@ -102,17 +102,8 @@ export default {
         ...mapState(['userInfo', 'organization'])
     },
     created() {
-        // this.$http
-        //     .get('organization/getByUserId/' + this.userInfo.id)
-        //     .then(res => {
-        //         this.formData = res;
-        //     })
-        //     .catch(e => {
-        //         console.log(e);
-        //         this.$message.error(e.error);
-        //     });
         this.formData = this.organization;
-        this.examinationAgency = this.organization.examinationAgency;
+        this.examinationAgency = this.organization.gradingOrganizationId;
         this.$http
             .get('/district/NJ', { size: 1000, query: { del: false } })
             .then(res => {
@@ -129,6 +120,22 @@ export default {
                 console.log(e);
                 this.$message.error(e.error);
             });
+        this.$http
+            .post('/gradingOrganization/all', { size: 1000 }, { body: 'json' })
+            .then(res => {
+                if (res.content.length > 0) {
+                    res.content.forEach(item => {
+                        this.examination.push({
+                            label: item.name,
+                            value: item.id
+                        });
+                    });
+                }
+            })
+            .catch(e => {
+                console.log(e);
+                this.$message.error(e.error);
+            });
     },
     data() {
         return {
@@ -137,10 +144,20 @@ export default {
             rules: {
                 name: { required: true, message: '请输入承办单位名称', trigger: 'blur' },
                 owner: { required: true, message: '请输入负责人', trigger: 'blur' },
-                ownerEmail: { required: true, message: '请输入负责人邮箱', trigger: 'blur' },
-                ownerPhone: { required: true, message: '请输入负责人电话', trigger: 'blur' },
+                ownerEmail: {
+                    required: true,
+                    message: '请输入正确的邮箱',
+                    pattern: /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,
+                    trigger: 'blur'
+                },
+                ownerPhone: {
+                    required: true,
+                    message: '请输入正确的手机号',
+                    pattern: /^1[3-9]\d{9}$/,
+                    trigger: 'blur'
+                },
                 privacyPolicy: { required: true, message: '请输入法人姓名', trigger: 'blur' },
-                IDNo: { required: true, message: '请输入证件号码', trigger: 'blur' },
+                idNo: { required: true, message: '请输入证件号码', trigger: 'blur' },
                 uscc: { required: true, message: '请输入信用代码', trigger: 'blur' },
                 district: { required: true, message: '请选择地址', trigger: 'change' },
                 address: { required: true, message: '请输入详细地址', trigger: 'blur' },
@@ -148,9 +165,8 @@ export default {
                 businessLicense: { required: true, message: '请上传营业执照', trigger: 'change' }
             },
             districtOptions: [],
-            readonly: true,
             district: [],
-            examination: ['中国音乐学院', '中国艺术科技研究所', '北京舞蹈学院'],
+            examination: [],
             examinationAgency: ''
         };
     },
@@ -167,19 +183,18 @@ export default {
         },
         submit() {
             let data = { ...this.formData };
-            data.examinationAgency = this.examinationAgency;
+            data.gradingOrganizationId = this.examinationAgency;
             this.saving = true;
             this.$http
                 .post('/organization/save', data, { body: 'json' })
                 .then(res => {
                     this.saving = false;
-                    // this.$message.success('成功');
+                    // this.submitUser();
                     // this.$router.go(-1);
                 })
                 .catch(e => {
                     console.log(e);
                     this.saving = false;
-                    this.readonly = true;
                     this.$message.error(e.error);
                 });
         },
@@ -191,11 +206,11 @@ export default {
                 .then(res => {
                     this.saving = false;
                     this.$message.success('成功');
+                    // this.$router.go(0);
                 })
                 .catch(e => {
                     console.log(e);
                     this.saving = false;
-                    this.readonly = true;
                     this.$message.error(e.error);
                 });
         },

+ 113 - 3
src/main/vue/src/views/organization/RateEdit.vue

@@ -118,7 +118,58 @@
                     <div class="val">
                         <el-form-item prop="privacyPolicy" label="合作协议">
                             <file-upload v-model="formData.privacyPolicy" :readonly="readonly"></file-upload>
-                            <!-- <single-upload v-model="formData.privacyPolicy"></single-upload> -->
+                        </el-form-item>
+                    </div>
+                </div>
+                <el-form-item>
+                    <el-button type="primary" size="small" @click="addParamater()">新增</el-button>
+                </el-form-item>
+                <div class="add-con" v-for="(item, index) in productParameters" :key="index">
+                    <div v-if="!item.del">
+                        <div class="parameters1">
+                            <div class="val">
+                                <el-form-item prop="district" label="考级机构">
+                                    <el-select v-model="formData.district" style="width:190px">
+                                        <el-option
+                                            v-for="item in districts"
+                                            :key="item.id"
+                                            :value="item.name"
+                                            :label="item.name"
+                                            :disabled="readonly"
+                                        ></el-option>
+                                    </el-select>
+                                </el-form-item>
+                            </div>
+                            <div class="val">
+                                <el-form-item prop="district" label="代理专业">
+                                    <el-select v-model="formData.district" style="width:190px">
+                                        <el-option
+                                            v-for="item in districts"
+                                            :key="item.id"
+                                            :value="item.name"
+                                            :label="item.name"
+                                            :disabled="readonly"
+                                        ></el-option>
+                                    </el-select>
+                                </el-form-item>
+                            </div>
+                        </div>
+                        <div class="info-item address">
+                            <div class="val">
+                                <el-form-item prop="privacyPolicy" label="合作协议">
+                                    <file-upload v-model="formData.privacyPolicy" :readonly="readonly"></file-upload>
+                                </el-form-item>
+                            </div>
+                        </div>
+                        <el-form-item>
+                            <el-button
+                                class="del"
+                                type="danger"
+                                v-if="!hasChild(item)"
+                                size="small"
+                                icon="el-icon-delete"
+                                @click="del(item, index)"
+                            ></el-button>
                         </el-form-item>
                     </div>
                 </div>
@@ -422,10 +473,62 @@ export default {
                     }
                 ]
             },
+            productParameters: [],
             collaborates: []
         };
     },
     methods: {
+        addParamater(info, index) {
+            const productParameters = [...this.productParameters];
+            if (info) {
+                info.value = '';
+                info.children.push({
+                    chName: '',
+                    enName: '',
+                    value: ''
+                });
+                productParameters[index] = info;
+            } else {
+                productParameters.push({
+                    chName: '',
+                    enName: '',
+                    value: '',
+                    children: []
+                });
+            }
+            this.productParameters = productParameters;
+        },
+        del(info, index, list, listIndex) {
+            this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'warning' })
+                .then(() => {
+                    const productParameters = [...this.productParameters];
+                    if (info.id) {
+                        info.del = true;
+                        if (list) {
+                            list[index] = info;
+                        } else {
+                            productParameters[index] = info;
+                        }
+                    } else if (list) {
+                        list.splice(index, 1);
+                    } else {
+                        productParameters.splice(index, 1);
+                    }
+                    if (list) {
+                        productParameters.children[listIndex] = list;
+                    }
+                    this.productParameters = productParameters;
+                    this.$message.success('删除成功');
+                })
+                .catch(e => {});
+        },
+        hasChild(info) {
+            info.children = info.children || [];
+            const childNum = [...info.children].filter(item => {
+                return !item.del;
+            }).length;
+            return !!childNum;
+        },
         handleClose(tag) {
             this.formData.examination.splice(this.formData.examination.indexOf(tag), 1);
         },
@@ -501,6 +604,9 @@ export default {
 <style lang="less" scoped>
 .edit-view {
     padding-left: 25%;
+    .add-con {
+        background: #eeeeee;
+    }
 }
 /deep/ .el-divider {
     margin-top: 30px;
@@ -513,6 +619,11 @@ export default {
     font-size: 20px;
     font-weight: 500;
 }
+
+.parameters1 {
+    display: flex;
+    align-items: center;
+}
 .info-content {
     // background: #f5f7fa;
     padding: 20px 10px 25px;
@@ -525,7 +636,6 @@ export default {
         display: flex;
         align-items: center;
         // margin-bottom: 10px;
-
         &.address {
             width: 100%;
             align-items: flex-start;
@@ -547,7 +657,7 @@ export default {
 
         .val {
             // width: 190px;
-            width: 300px;
+            // width: 300px;
         }
 
         .input {