Pārlūkot izejas kodu

Merge remote-tracking branch 'origin/master'

TRX 1 gadu atpakaļ
vecāks
revīzija
54fbe08207

+ 3 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/model/dictionary/AddDictionaryParam.java

@@ -13,6 +13,9 @@ import lombok.NoArgsConstructor;
 @NoArgsConstructor
 public class AddDictionaryParam {
 
+    @Schema(name = "id", description = "id", example = "665fc0ef9083d203896d3549")
+    private String id;
+
     @Schema(name = "projectId", description = "项目oid", example = "665fc0ef9083d203896d3549")
     @NotNull(message = "projectId不能为null")
     @NotEmpty(message = "projectId不能为空")

+ 18 - 0
FullCardClient/src/main/java/com/zhongshu/card/client/type/DictionaryUpdateStatus.java

@@ -0,0 +1,18 @@
+package com.zhongshu.card.client.type;
+
+import lombok.Getter;
+
+public enum DictionaryUpdateStatus {
+
+    NoInit("未初始化"),
+    Update("需要更新"),
+    LastVersion("已是最新版本");
+
+    @Getter
+    private String remark;
+
+    DictionaryUpdateStatus(String remark) {
+        this.remark = remark;
+
+    }
+}

+ 15 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/controller/dictionary/DictionaryController.java

@@ -4,6 +4,7 @@ import com.github.microservice.net.ResultContent;
 import com.zhongshu.card.client.model.dictionary.*;
 import com.zhongshu.card.client.model.pay.PeriodQueryModel;
 import com.zhongshu.card.client.model.pay.RechargeParam;
+import com.zhongshu.card.client.type.DictionaryUpdateStatus;
 import com.zhongshu.card.server.core.service.dictionary.DictionaryService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -90,4 +91,18 @@ public class DictionaryController {
     public Object deepTreeItem(@RequestBody DeepTreeItemQueryParam param){
         return dictionaryService.deepTreeItem(param.getProjectId(), param.getDictionaryKey(), param.getDictionaryId());
     }
+
+    @Operation(summary = "检查更新", description = "检查更新")
+    @RequestMapping(value = "updateCheck", method = RequestMethod.GET)
+    public ResultContent<DictionaryUpdateStatus> updateCheck(@RequestParam("projectId") String projectId){
+        return dictionaryService.updateCheck(projectId);
+    }
+
+    @Operation(summary = "更新标签字典初始化数据", description = "更新标签字典初始化数据")
+    @RequestMapping(value = "updateInit", method = RequestMethod.GET)
+    public ResultContent updateInit(@RequestParam("projectId") String projectId,
+                                    @RequestParam("coverName") boolean coverName,
+                                    @RequestParam("coverCustomize") boolean coverCustomize){
+        return dictionaryService.updateInit(projectId, coverName, coverCustomize);
+    }
 }

+ 5 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/dictionary/DictionaryDao.java

@@ -1,6 +1,7 @@
 package com.zhongshu.card.server.core.dao.dictionary;
 
 import com.github.microservice.components.data.mongo.mongo.dao.MongoDao;
+import com.zhongshu.card.client.type.DictionaryType;
 import com.zhongshu.card.server.core.dao.dictionary.extend.DictionaryDaoExtend;
 import com.zhongshu.card.server.core.domain.dictionary.Dictionary;
 
@@ -13,4 +14,8 @@ public interface DictionaryDao extends MongoDao<Dictionary>, DictionaryDaoExtend
     Dictionary findTopByProjectIdAndKey(String projectId, String key);
 
     List<Dictionary> findTopByProjectIdAndKeyIn(String projectId, List<String> keys);
+
+    List<Dictionary> findByProjectId(String projectId);
+
+    void deleteByProjectIdAndKeyNotInAndTypeIn(String projectId, List<String> keys, List<DictionaryType> type);
 }

+ 3 - 2
FullCardServer/src/main/java/com/zhongshu/card/server/core/dao/dictionary/DictionaryItemDao.java

@@ -1,6 +1,7 @@
 package com.zhongshu.card.server.core.dao.dictionary;
 
 import com.github.microservice.components.data.mongo.mongo.dao.MongoDao;
+import com.zhongshu.card.client.type.DictionaryType;
 import com.zhongshu.card.server.core.dao.dictionary.extend.DictionaryDaoExtend;
 import com.zhongshu.card.server.core.dao.dictionary.extend.DictionaryItemDaoExtend;
 import com.zhongshu.card.server.core.domain.dictionary.DictionaryItem;
@@ -17,7 +18,7 @@ public interface DictionaryItemDao extends MongoDao<DictionaryItem>, DictionaryI
 
     List<DictionaryItem> findByDictionary_Id(String dictionaryId);
 
-    List<DictionaryItem> findByDictionary_IdAndId(String dictionaryId, String id);
+    List<DictionaryItem> findByDictionary_IdIn(List<String> dictionaryIds);
 
-    List<DictionaryItem> findByParentId(String parentId);
+    void deleteByDictionary_IdAndKeyNotInAndTypeIn(String dictionaryId, List<String> keys, List<DictionaryType> type);
 }

+ 43 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/dataConfig/DictionaryInitConfig.java

@@ -0,0 +1,43 @@
+package com.zhongshu.card.server.core.dataConfig;
+
+import com.zhongshu.card.client.type.DictionaryType;
+import com.zhongshu.card.server.core.domain.dictionary.Dictionary;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.xmlbeans.impl.xb.xsdschema.Public;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Data
+@Component
+@NoArgsConstructor
+@AllArgsConstructor
+@ConfigurationProperties(prefix = "dictionary")
+public class DictionaryInitConfig {
+
+    private List<Dictionary> dictionaryList;
+
+
+    @Data
+    public static class Dictionary{
+
+        private String key;
+
+        private String name;
+
+        private DictionaryType type;
+
+        private String description;
+
+        private Integer sort;
+
+        private List<Dictionary> item;
+
+    }
+
+
+}

+ 122 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/init/DictionaryInit.java

@@ -0,0 +1,122 @@
+package com.zhongshu.card.server.core.init;
+
+import com.github.microservice.auth.security.type.AuthType;
+import com.zhongshu.card.client.type.DictionaryType;
+import com.zhongshu.card.server.core.dao.dictionary.DictionaryDao;
+import com.zhongshu.card.server.core.dao.dictionary.DictionaryItemDao;
+import com.zhongshu.card.server.core.dao.org.OrganizationDao;
+import com.zhongshu.card.server.core.dataConfig.DictionaryInitConfig;
+import com.zhongshu.card.server.core.domain.dictionary.Dictionary;
+import com.zhongshu.card.server.core.domain.dictionary.DictionaryItem;
+import com.zhongshu.card.server.core.domain.org.Organization;
+import com.zhongshu.card.server.core.service.dictionary.DictionaryService;
+import lombok.extern.slf4j.Slf4j;
+import org.bson.types.ObjectId;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@Component
+@Slf4j
+public class DictionaryInit implements ApplicationRunner {
+
+    @Autowired
+    DictionaryDao dictionaryDao;
+
+    @Autowired
+    DictionaryItemDao dictionaryItemDao;
+
+    @Autowired
+    DictionaryInitConfig dictionaryInitConfig;
+
+    @Autowired
+    OrganizationDao organizationDao;
+
+
+    public void init(){
+        List<DictionaryInitConfig.Dictionary> dictionaryList = dictionaryInitConfig.getDictionaryList();
+
+        if (dictionaryList == null || dictionaryList.isEmpty()) {
+            log.warn("字典初始化数据为空");
+            return;
+        }
+
+        List<Organization> project = organizationDao.findByAuthType(AuthType.Project);
+
+        if (project == null || project.isEmpty()) {
+            return;
+        }
+
+        for (Organization organization : project) {
+            initDictionary(organization.getProjectOid(), dictionaryList);
+        }
+        log.info("字典数据初始化完成!");
+    }
+
+    public void initDictionary(String projectId, List<DictionaryInitConfig.Dictionary> dictionaryList) {
+        for(DictionaryInitConfig.Dictionary dict : dictionaryList){
+            Dictionary dictionary = syncDictionary(projectId, dict);
+            if (dict.getItem() != null) {
+                for (DictionaryInitConfig.Dictionary item : dict.getItem()){
+                    syncDictionaryItem(item, null, dictionary);
+                }
+            }
+        }
+    }
+
+    private Dictionary syncDictionary(String projectId, DictionaryInitConfig.Dictionary dict) {
+        Dictionary dictionary = dictionaryDao.findTopByProjectIdAndKey(projectId, dict.getKey());
+        if (dictionary == null) {
+            dictionary = new Dictionary();
+            BeanUtils.copyProperties(dict, dictionary);
+            dictionary.setProjectId(projectId);
+            dictionary.setType(DictionaryType.Standard);
+            dictionary.setDisabled(false);
+            dictionaryDao.save(dictionary);
+        }
+        return dictionary;
+    }
+
+    private void syncDictionaryItem(DictionaryInitConfig.Dictionary dict, DictionaryItem parent, Dictionary dictionary){
+        DictionaryItem item = dictionaryItemDao.findTopByDictionary_IdAndKey(dictionary.getId(), dict.getKey());
+
+        if (item == null) {
+            item = new DictionaryItem();
+            BeanUtils.copyProperties(dict, item);
+            if (parent != null) {
+                item.setParentId(parent.getId());
+            }
+            item.setDictionary(dictionary);
+            item.setType(DictionaryType.Standard);
+            String id = new ObjectId().toHexString();
+            item.setId(id);
+            item.setIdString(id);
+            item.setCreateTime(System.currentTimeMillis());
+            item.setDisable(false);
+            dictionaryItemDao.save(item);
+        }
+
+        if (dict.getItem() !=null && !dict.getItem().isEmpty()){
+            for (DictionaryInitConfig.Dictionary children: dict.getItem()){
+                syncDictionaryItem(children, item, dictionary);
+            }
+        }
+    }
+
+
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+        init();
+    }
+}

+ 170 - 1
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/dictionary/DictionaryService.java

@@ -1,21 +1,26 @@
 package com.zhongshu.card.server.core.service.dictionary;
 
+import ch.qos.logback.core.joran.conditional.IfAction;
 import com.github.microservice.auth.security.helper.AuthHelper;
 import com.github.microservice.components.data.base.util.PageEntityUtil;
 import com.github.microservice.components.data.mongo.mongo.domain.SuperEntity;
 import com.github.microservice.net.ResultContent;
 import com.zhongshu.card.client.model.dictionary.*;
 import com.zhongshu.card.client.type.DictionaryType;
+import com.zhongshu.card.client.type.DictionaryUpdateStatus;
 import com.zhongshu.card.server.core.dao.dictionary.DictionaryDao;
 import com.zhongshu.card.server.core.dao.dictionary.DictionaryItemDao;
+import com.zhongshu.card.server.core.dataConfig.DictionaryInitConfig;
 import com.zhongshu.card.server.core.domain.dictionary.Dictionary;
 import com.zhongshu.card.server.core.domain.dictionary.DictionaryItem;
+import com.zhongshu.card.server.core.domain.org.Organization;
 import com.zhongshu.card.server.core.model.dictionary.DItemChildrenResult;
 import com.zhongshu.card.server.core.service.base.SuperService;
 import org.apache.commons.lang3.StringUtils;
 import org.bson.types.ObjectId;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.KeysetScrollPosition;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
@@ -36,7 +41,7 @@ public class DictionaryService extends SuperService {
     private DictionaryItemDao dictionaryItemDao;
 
     @Autowired
-    AuthHelper authHelper;
+    DictionaryInitConfig dictionaryInitConfig;
 
     public ResultContent init(){
         return null;
@@ -52,6 +57,13 @@ public class DictionaryService extends SuperService {
         if (byProjectIdAndKey != null){
             return ResultContent.buildFail("字典编码已存在");
         }
+
+        if (StringUtils.isNotBlank(param.getId())){
+            UpdateDictionaryParam updateParam = new UpdateDictionaryParam();
+            BeanUtils.copyProperties(param, updateParam);
+            return updateDictionary(updateParam);
+        }
+
         Dictionary dictionary = new Dictionary();
 
         BeanUtils.copyProperties(param, dictionary);
@@ -134,6 +146,10 @@ public class DictionaryService extends SuperService {
             return ResultContent.buildFail("字典不存在");
         }
 
+        if (dictionary.getType().equals(DictionaryType.Standard)){
+            return ResultContent.buildFail("标准字典不允许添加项");
+        }
+
         DictionaryItem dictionaryItem = new DictionaryItem();
         BeanUtils.copyProperties(param, dictionaryItem, "id");
         dictionaryItem.setType(DictionaryType.Customize);
@@ -375,6 +391,159 @@ public class DictionaryService extends SuperService {
         return rootItems;
     }
 
+    /**
+     * 更新检查
+     */
+    public ResultContent<DictionaryUpdateStatus> updateCheck(String projectId){
+        if (StringUtils.isBlank(projectId)){
+            projectId = getCurrentProjectOid();
+        }
+
+        if (StringUtils.isBlank(projectId)){
+            return ResultContent.buildFail("项目id不能未空");
+        }
+        return ResultContent.buildContent(getUpdateStatus(projectId));
+    }
+
+
+    public DictionaryUpdateStatus getUpdateStatus(String projectId){
+        List<DictionaryInitConfig.Dictionary> initDicList = dictionaryInitConfig.getDictionaryList();
+        List<String> initDictKeys = new ArrayList<>();
+        List<String> initItemKeys = new ArrayList<>();
+        getConfigKey(initDicList, initDictKeys, initItemKeys);
+
+        List<Dictionary> dic = dictionaryDao.findByProjectId(projectId);
+        if (dic.isEmpty()){//未初始化
+            return DictionaryUpdateStatus.NoInit;
+        }
+        List<String> dictKeys = new ArrayList<>(dic.stream().map(Dictionary::getKey).toList());
+
+        List<DictionaryItem> item = dictionaryItemDao.findByDictionary_IdIn(dic.stream().map(SuperEntity::getId).toList());
+        List<String> itemKeys = item.stream().map(DictionaryItem::getKey).toList();
+
+        if (initDictKeys.size() != dictKeys.size() || initItemKeys != itemKeys){//需要更新
+            return DictionaryUpdateStatus.Update;
+        }
+        //无需更新
+        return DictionaryUpdateStatus.LastVersion;
+    }
+
+    private void getConfigKey(List<DictionaryInitConfig.Dictionary> dictionaryList, List<String> dictKeys, List<String> itemKeys){
+
+        for (DictionaryInitConfig.Dictionary dictionary : dictionaryList) {
+            dictKeys.add(dictionary.getKey());
+            if (dictionary.getItem() != null && !dictionary.getItem().isEmpty()){
+                getConfigItemKey(dictionary.getItem(), itemKeys);
+            }
+        }
+    }
+
+    private void getConfigItemKey(List<DictionaryInitConfig.Dictionary> dictionaryList, List<String> keys){
+        for (DictionaryInitConfig.Dictionary dictionary : dictionaryList) {
+            keys.add(dictionary.getKey());
+            if (dictionary.getItem() != null && !dictionary.getItem().isEmpty()){
+                getConfigItemKey(dictionary.getItem(), keys);
+            }
+        }
+    }
+
+    /**
+     * 更新标签字典初始化数据
+     * @return
+     */
+    public ResultContent updateInit(String projectId, boolean coverName, boolean coverCustomize){
+        DictionaryUpdateStatus updateStatus = getUpdateStatus(projectId);
+
+        if (updateStatus.equals(DictionaryUpdateStatus.LastVersion)){
+            return ResultContent.buildFail("已是最新版本,无需修复或更新");
+        }
+        //TODO 更新至最新版本
+
+        List<DictionaryInitConfig.Dictionary> dictionaryList = dictionaryInitConfig.getDictionaryList();
+        if (dictionaryList == null || dictionaryList.isEmpty()) {
+            return ResultContent.buildFail("初始化数据不存在");
+        }
+
+        List<DictionaryType> typeList = new ArrayList<>(List.of(DictionaryType.Standard));
+
+        if (coverCustomize){
+            typeList.add(DictionaryType.Customize);
+        }
+
+        updateInitDictionary(projectId, dictionaryList, coverName, typeList);
+
+        List<String> initDictKeys = new ArrayList<>();
+        List<String> initItemKeys = new ArrayList<>();
+
+        getConfigKey(dictionaryList, initDictKeys, initItemKeys);
+
+        dictionaryDao.deleteByProjectIdAndKeyNotInAndTypeIn(projectId, initDictKeys, typeList);
+
+        return ResultContent.buildSuccess();
+    }
+
+
+    public void updateInitDictionary(String projectId, List<DictionaryInitConfig.Dictionary> dictionaryList, boolean coverName, List<DictionaryType> typeList) {
+        for(DictionaryInitConfig.Dictionary dict : dictionaryList){
+            Dictionary dictionary = syncDictionary(projectId, dict, coverName);
+            if (dict.getItem() != null) {
+                List<String> itemKeys = dict.getItem().stream().map(DictionaryInitConfig.Dictionary::getKey).toList();
+                dictionaryItemDao.deleteByDictionary_IdAndKeyNotInAndTypeIn(dictionary.getId(), itemKeys, typeList);
+                for (DictionaryInitConfig.Dictionary item : dict.getItem()){
+                    syncDictionaryItem(item, null, dictionary, coverName);
+                }
+            }
+        }
+    }
+
+    private Dictionary syncDictionary(String projectId, DictionaryInitConfig.Dictionary dict, boolean coverName) {
+        Dictionary dictionary = dictionaryDao.findTopByProjectIdAndKey(projectId, dict.getKey());
+        if (dictionary == null) {
+            dictionary = new Dictionary();
+            BeanUtils.copyProperties(dict, dictionary);
+            dictionary.setProjectId(projectId);
+            dictionary.setType(DictionaryType.Standard);
+            dictionary.setDisabled(false);
+            dictionary.setId(new ObjectId().toHexString());
+            dictionaryDao.save(dictionary);
+        }else if (coverName){
+            dictionary.setName(dict.getName());
+            dictionary.setDescription(dict.getDescription());
+            dictionaryDao.save(dictionary);
+        }
+        return dictionary;
+    }
+
+    private void syncDictionaryItem(DictionaryInitConfig.Dictionary dict, DictionaryItem parent, Dictionary dictionary, boolean coverName) {
+        DictionaryItem item = dictionaryItemDao.findTopByDictionary_IdAndKey(dictionary.getId(), dict.getKey());
+
+        if (item == null) {
+            item = new DictionaryItem();
+            BeanUtils.copyProperties(dict, item);
+            if (parent != null) {
+                item.setParentId(parent.getId());
+            }
+            item.setDictionary(dictionary);
+            item.setType(DictionaryType.Standard);
+            String id = new ObjectId().toHexString();
+            item.setId(id);
+            item.setIdString(id);
+            item.setCreateTime(System.currentTimeMillis());
+            item.setDisable(false);
+            dictionaryItemDao.save(item);
+        }else if (coverName){
+            item.setName(dict.getName());
+            item.setDescription(dict.getDescription());
+
+        }
+
+        if (dict.getItem() !=null && !dict.getItem().isEmpty()){
+            for (DictionaryInitConfig.Dictionary children: dict.getItem()){
+                syncDictionaryItem(children, item, dictionary, coverName);
+            }
+        }
+    }
+
 //    /**
 //     * 字典项向下查询
 //     */

+ 50 - 3
FullCardServer/src/main/resources/application-dev.yml

@@ -94,7 +94,7 @@ iotcenter:
 #        web: trace
 #debug: true
 #trace: true
-
+#    org.springframework.security: trace
 logging:
   level:
     com:
@@ -102,5 +102,52 @@ logging:
         microservice:
           core:
             runner: debug
-
-#    org.springframework.security: trace
+dictionary:
+  dictionary-list:
+    - { key: sys_sex, name: 性别, description: 用户性别, sort: 1, item:[
+                                                              { key: Male, name: 男, description: 男, sort: 1 },
+                                                              { key: Female, name: 女, description: 女, sort: 2 } ]}
+    - { key: sys_user_name, name: 姓名, description: 用户姓名, sort: 2 }
+    - { key: sys_user_number, name: 公号/学号, description: 公号/学号, sort: 3 }
+    - { key: sys_user_certificate, name: 证件, description: 证件号码, sort: 4, item:[
+                                                                           { key: IDCard, name: 身份证, description: 身份证号码, sort: 1},
+                                                                           { key: Passport, name: 护照, description: 护照号码, sort: 2}]}
+    - { key: sys_user_org, name: 机构, description: 机构, sort: 5 }
+    - { key: sys_user_type, name: 人员类型, description: 人员类型, sort: 6, item:[
+                                                                      {key: Consumer, name: 普通用户, description: 普通用户, sort: 1},
+                                                                      {key: Platform, name: 平台用户, description: 平台用户, sort: 2},
+                                                                      {key: Student, name: 学生, description: 学生, sort: 3},
+                                                                      {key: Teacher, name: 老师, description: 老师, sort: 4},
+                                                                      {key: ConsumerUser, name: c端用户, description: c端用户, sort: 5},
+                                                                      {key: SuperAdmin, name: 超级管理员用户, description: 超级管理员用户, sort: 6}]}
+    - { key: sys_user_status, name: 人员状态, description: 人员状态, sort: 7,item:[
+                                                                       {key: Normal, name: 正常, description: 正常, sort: 1},
+                                                                       {key: Locked, name: 禁用, description: 禁用, sort: 2}]}
+    - { key: sys_card_number, name: 卡号, description: 卡号, sort: 8 }
+    - { key: sys_card_type, name: 卡片类型, description: 卡片类型, sort: 9, item:[
+                                                                      {key: SevenCard, name: 七芯卡, description: 七芯卡, sort: 1},
+                                                                      {key: SuperSIM, name: 超级SIM卡, description: 超级SIM卡, sort: 2},
+                                                                      {key: IC, name: IC卡, description: IC卡, sort: 3}]}
+    - { key: sys_card_status, name: 卡片状态, description: 卡片状态, sort: 10, item:[
+                                                                         {key: Enable, name: 正常, description: 正常, sort: 1},
+                                                                         {key: Lock, name: 已锁定, description: 已锁定, sort: 2},
+                                                                         {key: Loss, name: 已挂失, description: 已挂失, sort: 3}]}
+    - { key: sys_org_number, name: 机构编号, description: 机构编号, sort: 11 }
+    - { key: sys_org_name, name: 机构名称, description: 机构名称, sort: 12 }
+    - { key: sys_org_type, name: 机构类型, description: 机构类型, sort: 13, item:[
+                                                                      {key: User, name: 用户, description: 用户, sort: 1},
+                                                                      {key: Platform, name: 平台, description: 平台, sort: 2},
+                                                                      {key: Enterprise, name: 企业, description: 企业, sort: 3},
+                                                                      {key: Project, name: 项目, description: 项目, sort: 4},
+                                                                      {key: School, name: 学校, description: 学校, sort: 5},
+                                                                      {key: Shop, name: 店铺, description: 店铺, sort: 6},
+                                                                      {key: BusinessMain, name: 供应商, description: 供应商, sort: 7},
+                                                                      {key: CommonOrg, name: 通用机构, description: 通用机构, sort: 8}]}
+    - { key: sys_org_status, name: 机构状态, description: 机构状态, sort: 14, item:[
+                                                                        {key: Normal, name: 正常, description: 正常, sort: 1},
+                                                                        {key: Locked, name: 禁用, description: 禁用, sort: 2},
+                                                                        {key: Frozen, name: 冻结, description: 冻结, sort: 3}]}
+    - { key: sys_project_type, name: 项目类型, description: 项目类型, sort: 15, item:[
+                                                                          {key: School, name: 学校, description: 学校, sort: 1},
+                                                                          {key: Hospital, name: 医院, description: 医院, sort: 2}]}
+    - { key: sys_project_status, name: 项目状态, description: 项目状态, sort: 16 }