Kaynağa Gözat

Merge branch 'develop' of http://106.12.23.251:10080/TEAMMODEL/TEAMModelOS into develop

chenmy 6 yıl önce
ebeveyn
işleme
d89b7a6bbb

+ 3 - 0
TEAMModelOS.SDK/Context/Filters/HttpGlobalExceptionFilter.cs

@@ -58,6 +58,9 @@ namespace TEAMModelOS.SDK.Context.Filters
                     case 500:
                         msg = context.Exception.Message;
                         break;
+                    case 403:
+                        msg = context.Exception.Message;
+                        break;
                     default:
                         msg = "Unknown Error";
                         break;

+ 3 - 0
TEAMModelOS.SDK/Context/Filters/HttpGlobalExceptionInvoke.cs

@@ -69,6 +69,9 @@ namespace TEAMModelOS.SDK.Context.Filter
                         case 500:
                             msg = exs.Message;
                             break;
+                        case 403:
+                            msg = exs.Message;
+                            break;
                         default:
                             msg = "Unknown Error";
                             break;

+ 1 - 0
TEAMModelOS.SDK/Extension/JwtAuth/JwtAuthExtension.cs

@@ -78,6 +78,7 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth
             //自定义授权
             services.AddAuthorization(auth =>
             {
+                auth.AddPolicy("Admin", policy => policy.RequireRole("Admin,Root,SchoolAdmin,Teacher").Build());
                 auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                     .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                     .RequireAuthenticatedUser()

+ 25 - 3
TEAMModelOS.SDK/Extension/JwtAuth/JwtHelper/JwtHelper.cs

@@ -43,7 +43,8 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
             claims.Add(new Claim(JwtClaimTypes.Issuer, setting.Issuer));
             claims.Add(new Claim(JwtClaimTypes.Scope, claimModel.Scope));
             claims.Add(new Claim(JwtClaimTypes.JwtId, Guid.NewGuid().ToString()));
-            claims.AddRange(claimModel.Roles.ToArray().Select(s=>new Claim(JwtClaimTypes.Role,s)));
+           //claims.AddRange(claimModel.Roles.Select(s=>new Claim(JwtClaimTypes.Role, s)));
+            //claims.AddRange(claimModel.Claims.Select(s => new Claim(ClaimTypes.Role, s)));
             string path = BaseConfigModel.ContentRootPath;
             RSACryptoServiceProvider provider = RsaHelper.LoadCertificateFile(path + "/JwtRsaFile/private.pem");
             RsaSecurityKey rsaSecurity = new RsaSecurityKey(provider);
@@ -69,11 +70,32 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
 
             ///https://www.cnblogs.com/JacZhu/p/6837676.html#Update2.0  刷新     用户的 Token 在过期时间之内根本无法手动设置失效,随之而来的还有重放攻击等等问题
 
+
             var jwtHandler = new JwtSecurityTokenHandler();
             JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);
+            object role = new object(); ;
+            jwtToken.Payload.TryGetValue(ClaimTypes.Role, out role);
+          
+            //var tm = new TokenModelJWT
+            //{
+            //    Uid = (jwtToken.Id).ObjToInt(),
+            //    Role = role != null ? role.ObjToString() : "",
+            //};
+
+
+
+           // var jwtHandler = new JwtSecurityTokenHandler();
+           // JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);
             ClaimModel claimModel = new ClaimModel();
-            object role = new object();
-            claimModel.Claim = jwtToken.Claims.ToDictionary(claim => claim.Type, claim => claim.Value);
+            //object role = new object();
+           // claimModel.Claim = jwtToken.Claims.ToDictionary(claim => claim.Type, claim => claim.Value);
+            Dictionary<string, object> claimDict = new Dictionary<string, object>();
+            foreach (Claim claim in jwtToken.Claims)
+            {
+                claimDict.TryAdd(claim.Type, claim.Value);
+            }
+            claimDict[ClaimTypes.Role] = role;
+            claimModel.Claim = claimDict;
             claimModel.Claims = jwtToken.Claims.ToList();
             jwtToken.Payload.TryGetValue(JwtClaimTypes.Role, out role);
             if(role!=null)claimModel.Roles=role.ToString().Split(",").ToList();

+ 2 - 2
TEAMModelOS.SDK/Extension/JwtAuth/Models/ClaimModel.cs

@@ -8,7 +8,7 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.Models
     {
         public ClaimModel() {
             Claims = new List<Claim>();
-            Claim = new Dictionary<string, string>();
+            Claim = new Dictionary<string, object>();
             Roles = new List<string>();
         }
 
@@ -20,7 +20,7 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.Models
         /// <summary>
         /// 用户身份信息
         /// </summary>
-        public Dictionary<string ,string> Claim { get; set; }
+        public Dictionary<string ,object> Claim { get; set; }
         /// <summary>
         /// 用户角色信息
         /// </summary>

+ 13 - 4
TEAMModelOS.SDK/Helper/Network/HttpHelper/HttpContextHelper.cs

@@ -97,7 +97,7 @@ namespace TEAMModelOS.SDK.Helper.Network.HttpHelper
             }
             return aktoken;
         }
-        public static string GetLoginUser(IHttpContextAccessor httpContextAccessor ,string claimType) {
+        public static List<string> GetLoginUser(IHttpContextAccessor httpContextAccessor ,string claimType) {
             var tokenHeader = "";
             HttpRequest request = httpContextAccessor.HttpContext.Request;
             if (request.Headers.ContainsKey(Constants.AUTHORIZATION))
@@ -111,12 +111,21 @@ namespace TEAMModelOS.SDK.Helper.Network.HttpHelper
                 tokenHeader = request.Query[Constants.ACCESS_TOKEN];
                 tokenHeader = tokenHeader.Trim();
             }
-            if (string.IsNullOrEmpty(tokenHeader)) {
-                return "";
+            if (string.IsNullOrEmpty(tokenHeader))
+            {
+                return null;
             }
             ClaimModel claimModel = JwtHelper.SerializeJWT(tokenHeader);
             claimModel.Claim.TryGetValue(claimType, out var claimValue);
-            return claimValue; 
+            List<string> claimValues = new List<string>();
+            foreach (Claim claim in claimModel.Claims)
+            {
+                if (claim.Type.Equals(claimType))
+                {
+                    claimValues.Add(claim.Value);
+                }
+            }
+            return claimValues;
         }
     }
 }

+ 2 - 1
TEAMModelOS.Service/Core/Implements/LoginInfoService.cs

@@ -132,7 +132,7 @@ namespace TEAMModelOS.Service.Core.Implements
 
                 var dateTime = DateTimeHelper.ConvertToTimeStamp10(DateTime.Now);
                 var expExt=claimModel.Claim.TryGetValue("exp",out var exp);
-                if (expExt==false || dateTime > long.Parse(exp))
+                if (expExt==false || dateTime > long.Parse(exp.ToString()))
                 {
                     throw new BizException(401, "Unauthorized");
                 }
@@ -176,6 +176,7 @@ namespace TEAMModelOS.Service.Core.Implements
             model.Claims.Add(new Claim(JwtClaimTypes.Id, loginInfo.TeamModelId));
             ////保护隐私
             //model.Claims.Add(new Claim(JwtClaimTypes.PhoneNumber, loginInfo.Phone));
+            model.Claims.AddRange(role.Split(',').Select(s => new Claim(JwtClaimTypes.Role, s)));
             model.Roles.Add(role);
             JwtResponse jwtResponse = JwtHelper.IssueJWT(model, _options.Value);
             return jwtResponse;

Dosya farkı çok büyük olduğundan ihmal edildi
+ 3 - 2
TEAMModelOS.Service/Core/Implements/SchoolService.cs


+ 327 - 0
TEAMModelOS/ClientApp/common/KnowPoint.vue

@@ -0,0 +1,327 @@
+<template>
+  <div class="know-main center">
+    <div class="content-wrap">
+      <div class="header-wrap">
+        <Input placeholder="关键词搜索知识点" style="width:25% !important;" />
+        <div class="list-type center">
+          <Icon type="md-menu" size="20" :class="listType==0?'list-type-active':''" @click="changeListType(0)"/>
+          <Icon type="ios-keypad" size="20" :class="listType==1?'list-type-active':''" @click="changeListType(1)"/>
+        </div>
+        <div class="header-right">
+          <div class="header-right-item">
+            <Icon type="logo-buffer" size="18" />
+            <span>新增知识点</span>
+          </div>
+          <div class="header-right-item">
+            <Icon type="ios-browsers" size="18" />
+            <span>新增知识块</span>
+          </div>
+          <div class="header-right-item">
+            <Icon type="ios-cloud-download" size="18" />
+            <span>导入知识点</span>
+          </div>
+        </div>
+      </div>
+      <div class="list-wrap">
+        <!-- 知识块 -->
+        <div class="list-col" v-if="isShowBlock">
+          <Collapse simple accordion @on-change="collapseChange">
+            <Panel v-for="(item,index) in knowBlockList" class="know-block-item" :key="index" :name="item.period">
+              <span class="know-block-name">{{item.name}} | {{item.id}}</span>
+              <span class="know-block-builder">建立者 | {{item.builder}}</span>
+              <span class="k-block-tools">
+                <Icon type="md-create" />
+                <Icon type="md-trash" />
+              </span>
+              <div slot="content" class="knowpoints">
+                <div class="knowpoint-item" v-for="(item,index) in knowPointList" @mouseover="knowMouseover" @mouseout="knowMouseout">
+                  <span>{{item.name}} </span>
+                  <span class="k-tools">
+                    <Icon type="md-create" />
+                    <Icon type="md-trash" />
+                  </span>
+                </div>
+              </div>
+            </Panel>
+          </Collapse>
+        </div>
+        <!-- 知识点仓库 -->
+        <div class="list-col list-knowpoints" v-else>
+          <div class="knowpoints">
+            <div class="knowpoint-item" v-for="(item,index) in knowPointList"  @mouseover="knowMouseover" @mouseout="knowMouseout">
+              <span>{{item.name}} </span>
+              <span class="k-tools">
+                <Icon type="md-create" />
+                <Icon type="md-trash" />
+              </span>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script scoped>
+  export default {
+    name: "KnowPoint",
+    data() {
+      return {
+        knowPointList: [],
+        knowBlockList: [],
+        treeData: [],
+        isShowBlock: true,
+        listType: 0
+      }
+    },
+    created() {
+      for (let i = 0; i < 11; i++) {
+        this.knowPointList.push({
+          id: i,
+          name: "知识点名称_" + this.changeNumFormat(i),
+          termNum: i + 5
+        })
+
+        this.knowBlockList.push({
+          id: i,
+          name: "知识块名称",
+          period: i.toString(),
+          builder: "郭金凤",
+          userNum: i + 5
+        })
+      }
+    },
+    methods: {
+
+      //知识点与知识块切换
+      changeListType(status) {
+        this.listType = status;
+        this.isShowBlock = status == 0;
+      },
+      //数字格式转换
+      changeNumFormat(num) {
+        let nums = num.toString();
+        if (nums.length == 1) {
+          nums = '00' + nums;
+        } else if (nums.length == 2) {
+          nums = '0' + nums;
+        }
+        return nums;
+      },
+      //鼠标滑入事件显示操作选项
+      knowMouseover(e) {
+        e.stopPropagation();
+        e.currentTarget.lastElementChild.style.visibility = 'visible';
+      },
+      //鼠标滑出事件隐藏操作选项
+      knowMouseout(e) {
+        e.stopPropagation();
+        e.currentTarget.lastElementChild.style.visibility = 'hidden';
+      },
+      //折叠版切换回调
+        collapseChange(arr) {
+          let list = document.getElementsByClassName('k-block-tools');
+          for (let i = 0 ; i < list.length ;i++) {
+            if (arr.indexOf(i.toString()) != -1) {
+              list[i].style.visibility = "visible";
+            } else {
+              list[i].style.visibility = "hidden";
+            }
+        }
+      }
+    }
+  }
+</script>
+
+<style scoped>
+  .know-main {
+    width: 100%;
+    height: 100%;
+    background: #fff;
+    padding: 20px 20px 20px 0;
+    box-sizing: border-box;
+  }
+
+  .center {
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .centerCol {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .content-wrap {
+    width: 100%;
+    height: 100%;
+    border: 2px solid #464646;
+  }
+
+  .header-wrap {
+    position: relative;
+    width: 100%;
+    height: 50px;
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+    border-bottom: 2px solid #464646;
+  }
+
+  .header-wrap /deep/ .ivu-input {
+    height: 48px;
+    border: 0;
+    padding-left: 15px;
+    border-radius: 0 !important;
+    border-right: 2px solid #464646;
+    font-size: 14px;
+    font-weight: bold;
+    color: #464646;
+  }
+
+  .header-wrap /deep/ .ivu-input::-webkit-input-placeholder {
+    color: #464646;
+  }
+
+  .header-wrap /deep/ .ivu-input-suffix i {
+    line-height: 50px;
+  }
+
+  .header-right {
+    height: 100%;
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .header-right-item {
+    margin-right: 25px;
+    font-weight: 500;
+    font-size: 12px;
+    cursor: pointer;
+  }
+
+  .list-type .ivu-icon {
+    margin-left: 10px;
+    color: rgb(154,154,154);
+    cursor:pointer;
+  }
+
+  .list-type-active {
+    color: #fff !important;
+    background-color: rgb(154,154,154);
+    border-radius: 50%;
+    padding: 3px;
+  }
+
+  .list-wrap {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+    padding-bottom: 50px;
+  }
+
+  .list-col {
+    overflow-y: auto;
+    height: 100%;
+  }
+
+  .list-knowpoints {
+    padding-top:30px;
+  }
+
+  .list-wrap /deep/ .ivu-collapse > .ivu-collapse-item > .ivu-collapse-header {
+    height: 100px;
+    line-height: 100px;
+  }
+
+  .collapse-header {
+    display:flex;
+    flex-direction:column;
+    justify-content:center;
+  }
+
+  .know-block-item {
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    padding-left: 15px;
+    border-bottom: 1px solid #464646;
+    cursor: pointer;
+  }
+
+  .know-block-item:hover {
+    background: #fff;
+  }
+
+  .know-block-name {
+    font-size: 18px;
+    font-weight: 600;
+  }
+
+  .know-block-builder {
+    margin-left:15px;
+  }
+
+
+  .list-col::-webkit-scrollbar { /*滚动条整体样式*/
+    width: 0px; /*高宽分别对应横竖滚动条的尺寸*/
+    height: 1px;
+  }
+
+  .list-col:hover .ztree_box::-webkit-scrollbar {
+    width: 5px;
+  }
+
+  .list-col::-webkit-scrollbar-thumb { /*滚动条里面小方块*/
+    border-radius: 10px;
+    -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
+    background: #ffffff26;
+  }
+
+  .list-col::-webkit-scrollbar-track { /*滚动条里面轨道*/
+    background-color: #f4f4f400;
+  }
+
+  .knowpoints {
+    width:100%;
+    display:flex;
+    flex-direction:row;
+    flex-wrap:wrap;
+    padding: 0 10px;
+  }
+  .knowpoint-item {
+    padding:10px 20px;
+    margin:5px;
+    background:rgb(103,109,109);
+    color:rgb(232,233,233);
+    border-radius:100px;
+    font-size:12px;
+    cursor:pointer;
+  }
+  .knowpoint-item:hover{
+    background:rgb(179,179,179);
+    color:#fff !important;
+  }
+  .knowpoint-item .ivu-icon {
+    margin-left:5px;
+  }
+  .k-tools {
+    visibility:hidden;
+  }
+  .k-block-tools {
+    margin-left: 20px;
+    visibility: hidden;
+  }
+  .k-block-tools .ivu-icon {
+    margin-left: 15px;
+    font-size: 16px;
+  }
+</style>

+ 331 - 0
TEAMModelOS/ClientApp/common/Syllabus.vue

@@ -0,0 +1,331 @@
+<template>
+  <div class="syllabus-main center">
+    <div class="content-wrap">
+      <div class="header-wrap">
+        <Input placeholder="关键词搜索课纲" style="width:250px !important;" />
+        <div class="header-right">
+          <div class="header-right-item">
+            <Icon type="logo-buffer" size="18"/>
+            <span>新增科目</span>
+          </div>
+          <div class="header-right-item">
+            <Icon type="ios-browsers" size="18"/>
+            <span>新增册别/课纲</span>
+          </div>
+          <div class="header-right-item">
+            <Icon type="ios-cloud-download" size="18"/>
+            <span>导入课纲</span>
+          </div>
+        </div>
+      </div>
+
+      <div class="list-wrap">
+        <!-- 左边科目列表 -->
+        <div class="list-col list-left">
+          <div v-for="item in subjectList" :class='["subject-item", item.id==s_click_id ? "term-item-active" : ""]'   @mouseover="subjectMouseover(item.id)" @mouseout="subjectMouseout()" @click="subjectClick(item.id)">
+            <span class="subject-name">
+              <span>{{item.name}}</span>
+              <span class="s-block-tools" v-show="item.id==c_subject_id">
+                <Icon type="md-create" />
+                <Icon type="md-trash" />
+              </span>
+            </span>
+            <span class="subject-term-num">册数 | {{item.termNum}}</span>
+          </div>
+        </div>
+        <!-- 中间册别列表 -->
+        <div class="list-col list-middle">
+          <div v-for="item in termList" :class='["subject-item", "term-item", item.id==c_click_id ? "term-item-active" : ""]' @mouseover="termMouseover(item.id)" @mouseout="termMouseout()" @click="termClick(item.id)">
+            <span class="subject-name term-name">
+              <span class="term-name-title">{{item.name}} | {{item.count}}</span>
+              <span class="s-block-tools" v-show="item.id==c_term_id">
+                <Icon type="md-create" />
+                <Icon type="md-trash" />
+              </span>
+            </span>
+            <span class="term-period">{{item.period}} | {{item.term}}  <Icon type="md-arrow-dropdown" v-show="item.id==c_click_id" size="18" style="margin-bottom:3px" /></span>
+            <span class="term-userNum">
+              <span>共编使用者数 | {{item.userNum}} 名</span>
+              <span class="term-add-user" v-show="item.id==c_click_id">添加共编使用者</span>
+            </span>
+            <!-- 使用者列表 -->
+            <transition enter-active-class="animated slideInDown">
+              <div class="term-users" v-show="item.id==c_click_id">
+                <div class="term-user-item center" v-for="user in userList">
+                  <img class="term-user-img" :src="user.headImg" />
+                  <span class="term-user-name">{{user.name}} {{user.role}}</span>
+                </div>
+              </div>
+            </transition>
+          </div>
+        </div>
+        <!-- 右侧树形列表 -->
+        <div class="list-col list-right">
+          <Tree></Tree>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import Tree from './Tree.vue'
+  export default {
+    name: "Syllabus",
+    components: {
+      Tree: Tree
+    },
+    data() {
+      return {
+        subjectList: [],
+        termList: [],
+        treeData: [],
+        userList:[],
+        c_subject_id:0,
+        c_term_id: 0,
+        c_click_id: 0,
+        s_click_id:0
+      }
+    },
+    created() {
+      for (let i = 0; i < 8; i++) {
+        this.subjectList.push({
+          id:i,
+          name: "科目名称" + i,
+          termNum:i+5
+        })
+
+        this.termList.push({
+          id:i,
+          name: "册别名称",
+          period: "小学",
+          term: "一年级上学期",
+          count:i+10,
+          userNum:i+5
+        })
+
+        this.userList.push({
+          id:i,
+          headImg: "http://bj.bcebos.com/fc-feed/0/pic/4e8536fc11c43ad8ba36c921a61183a0.jpg",
+          name: "郭富城",
+          role:"老师"
+        })
+      }
+    },
+    methods: {
+      //鼠标滑入事件显示操作选项
+      subjectMouseover(id) {
+        this.c_subject_id = id;
+      },
+      //鼠标滑出事件隐藏操作选项
+      subjectMouseout() {
+        this.c_subject_id = null;
+      },
+      //册别鼠标滑入事件显示操作选项
+      termMouseover(id) {
+        this.c_term_id = id;
+      },
+      //册别鼠标滑出事件隐藏操作选项
+      termMouseout() {
+        this.c_term_id = null;
+      },
+      //册别点击事件
+      termClick(id) {
+        this.c_click_id = id;
+        this.c_term_id = id;
+      },
+      //科目点击事件
+      subjectClick(id) {
+        this.s_click_id = id;
+        this.c_subject_id = id;
+      }
+    }
+  }
+</script>
+
+<style scoped>
+  .syllabus-main {
+    width: 100%;
+    height: 100%;
+    background: #fff;
+    padding: 20px;
+    box-sizing: border-box;
+  }
+
+  .content-wrap {
+    width: 100%;
+    height: 100%;
+    border: 2px solid #464646;
+  }
+
+  .header-wrap {
+    position:relative;
+    width: 100%;
+    height: 50px;
+    display:flex;
+    flex-direction:row;
+    justify-content:space-between;
+    border-bottom: 2px solid #464646;
+  }
+
+  .header-wrap /deep/ .ivu-input {
+    height: 48px;
+    border: 0;
+    padding-left:15px;
+    border-radius: 0 !important;
+    border-right: 2px solid #464646;
+    font-size: 14px;
+    font-weight: bold;
+    color: #464646;
+  }
+
+  .header-wrap /deep/ .ivu-input::-webkit-input-placeholder {
+    color: #464646;
+  }
+
+  .header-wrap /deep/ .ivu-input-suffix i {
+    line-height: 50px;
+  }
+
+  .header-right {
+    height:100%;
+    display:flex;
+    flex-direction:row;
+    justify-content:center;
+    align-items:center;
+  }
+
+  .header-right-item {
+    margin-right:25px;
+    font-weight:500;
+    font-size:12px;
+    cursor:pointer;
+  }
+
+  .list-wrap {
+    width:100%;
+    height:100%;
+    display:flex;
+    flex-direction:row;
+    padding-bottom:50px;
+  }
+  .list-col {
+    height: 100%;
+    overflow-y:auto;
+  }
+
+  .list-left {
+    width:20%;
+    background-color:rgb(204,204,204);
+  }
+  .list-middle {
+    width: 35%;
+    background-color: rgb(230,230,230);
+    border-left: 1px solid #464646;
+    border-right: 1px solid #464646;
+  }
+  .list-right {
+    width: 45%;
+    background-color: rgb(242,242,242);
+  }
+  .subject-item {
+    width: 100%;
+    height: 80px;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    padding-left: 15px;
+    border-bottom: 1px solid #464646;
+    cursor: pointer;
+  }
+  .subject-item:hover{
+    background:#fff;
+  }
+
+  .subject-name {
+    font-size:18px;
+    font-weight:600;
+   }
+
+  .term-item {
+    height:auto;
+    padding:10px;
+  }
+
+  .term-item-active {
+    background:#fff;
+  }
+
+  .term-period {
+    margin: 5px 0;
+    font-size:14px;
+  }
+
+  .term-name-title {
+    font-size:18px;
+    font-weight:600;
+  }
+
+  .term-add-user {
+    text-decoration:underline;
+    cursor:pointer;
+  }
+
+  .term-users {
+    width: 100%;
+    background: #fff;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: wrap;
+    margin-top: 10px;
+  }
+  .term-user-item {
+    padding:5px;
+    margin:5px;
+  }
+  .term-user-img {
+    width: 25px;
+    height: 25px;
+    border-radius: 50%;
+  }
+  .term-user-name {
+    margin-left: 5px;
+    color: rgb(139, 139, 139);
+  }
+  .centerCol {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .list-col::-webkit-scrollbar { /*滚动条整体样式*/
+    width: 0px; /*高宽分别对应横竖滚动条的尺寸*/
+    height: 1px;
+  }
+
+  .list-col:hover .ztree_box::-webkit-scrollbar {
+    width: 5px;
+  }
+
+  .list-col::-webkit-scrollbar-thumb { /*滚动条里面小方块*/
+    border-radius: 10px;
+    -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
+    background: #ffffff26;
+  }
+
+  .list-col::-webkit-scrollbar-track { /*滚动条里面轨道*/
+    background: #f4f4f400;
+  }
+
+  .s-block-tools {
+    margin-left: 10px;
+  }
+
+  .s-block-tools .ivu-icon {
+    margin-left: 5px;
+    margin-bottom:2px;
+    font-size: 16px;
+    color: rgb(185, 185, 185);
+  }
+</style>

+ 756 - 0
TEAMModelOS/ClientApp/common/Tree.vue

@@ -0,0 +1,756 @@
+<template>
+  <div class="tree-main">
+
+    <Tree :data="treeData" :render="renderContent" ref="tree"></Tree>
+    <Modal v-model="modalFlag" title="添加新节点" ok-text="确认" cancel-text="取消" @on-ok="handleAddNode">
+      <Row class="modelRow">
+        <span>
+          当前章节:
+          <span style="margin-left:10px;">{{currentNode.title}}</span>
+        </span>
+      </Row>
+      <Row class="modelRow">
+        <span>章节类型:</span>
+        <RadioGroup v-model="nodeType" type="button">
+          <Radio label="章节"></Radio>
+          <Radio label="课件"></Radio>
+        </RadioGroup>
+      </Row>
+      <Row class="modelRow">
+        <span>章节名称:</span>
+        <Input v-model="inputValue" placeholder="输入新节点名称" style="width: 100%" />
+      </Row>
+    </Modal>
+    <Modal v-model="editFlag" title="修改节点" ok-text="确认" cancel-text="取消" @on-ok="handleUpdateNode">
+      <Row class="modelRow">
+        <span>
+          当前名称:
+          <span style="margin-left:10px;">{{currentNode.title}}</span>
+        </span>
+      </Row>
+      <Row class="modelRow">
+        <span>章节类型:</span>
+        <RadioGroup v-model="nodeType" type="button">
+          <Radio label="章节"></Radio>
+          <Radio label="课件"></Radio>
+        </RadioGroup>
+      </Row>
+      <Row class="modelRow">
+        <span>章节名称:</span>
+        <Input v-model="editValue" placeholder="输入节点新名称" style="width: 100%" />
+      </Row>
+    </Modal>
+  </div>
+</template>
+<script>
+  export default {
+    data() {
+      return {
+        bookSelect: "语文人教课标版四年级上册",
+        periodList: [],
+        subjectList: [],
+        versionList: [],
+        gradeList: [],
+        slideGradeList: [
+          {
+            value: "语文人教课标版四年级上册",
+            label: "语文人教课标版四年级上册"
+          },
+          {
+            value: "语文人教课标版五年级上册",
+            label: "语文人教课标版五年级上册"
+          },
+          {
+            value: "语文人教课标版六年级上册",
+            label: "语文人教课标版六年级上册"
+          },
+          {
+            value: "语文人教课标版七年级上册",
+            label: "语文人教课标版七年级上册"
+          },
+          {
+            value: "语文人教课标版八年级上册",
+            label: "语文人教课标版八年级上册"
+          },
+          {
+            value: "语文人教课标版九年级上册",
+            label: "语文人教课标版九年级上册"
+          }
+        ],
+        treeData: [
+          {
+            title: "语文人教课标版四年级上册",
+            order: 0,
+            expand: true,
+            render: (h, { root, node, data }) => {
+              return h(
+                "span",
+                {
+                  style: {
+                    display: "inline-block",
+                    position: "relative",
+                    width: "94%",
+                    textAlign: "left",
+                    paddingLeft: "10px",
+                    cursor: "pointer",
+                    height: "50px",
+                    lineHeight: "50px"
+                  },
+                  on: {
+                    click: () => {
+                      this.rootClick(data);
+                    }
+                  }
+                },
+                [
+                  h("span", [
+                    h("Icon", {
+                      props: {
+                        type: "md-filing"
+                      },
+                      style: {
+                        marginRight: "5px",
+                        display: "none"
+                      }
+                    }),
+                    h("span", { on: { click: () => { } } }, data.title)
+                  ]),
+
+                  h("Button", {
+                    props: {
+                      icon: "ios-add"
+                    },
+                    style: {
+                      position: "absolute",
+                      right: "30px",
+                      top: "15px",
+                      padding: "0 10px"
+                    },
+                    on: {
+                      click: e => {
+                        e.stopPropagation();
+                        this.appendClick(data);
+                      }
+                    }
+                  })
+
+
+                ]
+              );
+            },
+            children: [
+              {
+                title: "第一组",
+                order: 0,
+                expand: true,
+                children: [
+                  {
+                    title: "文言文两则",
+                    order: 0,
+                    expand: true,
+                    children: []
+                  },
+                  {
+                    title: "匆匆",
+                    order: 1,
+                    expand: true,
+                    children: []
+                  },
+                  {
+                    title: "桃花心木",
+                    order: 0,
+                    expand: true,
+                    children: []
+                  },
+                  {
+                    title: "顶碗少年",
+                    order: 1,
+                    expand: true,
+                    children: []
+                  },
+                  {
+                    title: "手指",
+                    order: 0,
+                    expand: true,
+                    children: []
+                  },
+                  {
+                    title: "北京的春节",
+                    order: 1,
+                    expand: true,
+                    children: []
+                  },
+                  {
+                    title: "各具特色的民居",
+                    order: 0,
+                    expand: true,
+                    children: []
+                  },
+                  {
+                    title: "和田的维吾尔",
+                    order: 1,
+                    expand: true,
+                    children: []
+                  }
+                ]
+              },
+              {
+                title: "第二组",
+                expand: true,
+                order: 1,
+                children: [
+                  {
+                    title: "十六年前的回忆",
+                    order: 0,
+                    expand: true,
+                    children: []
+                  },
+                  {
+                    title: "灯光",
+                    order: 1,
+                    expand: true,
+                    children: []
+                  },
+                  {
+                    title: "为人民服务",
+                    order: 2,
+                    expand: true,
+                    children: []
+                  }
+                ]
+              },
+              {
+                title: "第三组",
+                expand: true,
+                order: 1,
+                children: []
+              }
+            ]
+          }
+        ],
+        inputValue: "",
+        editValue: "",
+        modalFlag: false,
+        editFlag: false,
+        addBookFlag: false,
+        nodeType: "章节",
+        currentNode: "",
+        currentLiNode: "",
+        buttonProps: {
+          type: "default",
+          size: "small"
+        },
+        periodSelect: "",
+        subjectSelect: "",
+        versionSelect: "",
+        gradeSelect: "",
+        periodName: "",
+        subjectName: "",
+        versionName: "",
+        gradeName: "",
+      };
+    },
+
+    methods: {
+      renderContent(h, { root, node, data }) {
+        let that = this;
+        return h(
+          "span",
+          {
+            style: {
+              display: "inline-block",
+              width: "95%",
+              textAlign: "left",
+              paddingLeft: "2%",
+              cursor: "pointer",
+              position: "relative",
+              boxSizing: "border-box"
+            },
+            domProps: {
+              className: "singleClass"
+            },
+            on: {
+              click: () => {
+                this.titleClick(root, node, data, event);
+              },
+              mouseover: e => {
+                e.stopPropagation();
+                this.handleLiOver(event);
+              },
+              mouseleave: e => {
+                e.stopPropagation();
+                this.handleLiLeave(node, event);
+              }
+            }
+          },
+          [
+            h("span", [
+              h("Icon", {
+                props: {
+                  type:
+                    data.children && data.children.length > 0
+                      ? "md-albums"
+                      : "ios-paper-outline"
+                },
+                style: {
+                  marginRight: "5px",
+                  display: "none"
+                }
+              }),
+              h("span", data.nodeKey + '. ' + data.title)
+            ]),
+            h(
+              "span",
+              {
+                style: {
+                  float: "right",
+                  top: "10px",
+                  display: "none"
+                },
+                on: {
+                  mouseleave: e => {
+                    e.stopPropagation();
+                    //this.hideTools(event);
+                  },
+                },
+                domProps: {
+                  className: "tools"
+                }
+              },
+              [
+                h(
+                  "Icon",
+                  {
+                    props: {
+                      type: "md-add",
+                      title: "添加"
+                    },
+                    on: {
+                      click: e => {
+                        e.stopPropagation();
+                        this.appendClick(data);
+                      }
+                    }
+                  },
+                ),
+                h(
+                  "Icon",
+                  {
+                    props: {
+                      type: "md-remove"
+                    },
+                    on: {
+                      click: e => {
+                        e.stopPropagation();
+                        this.remove(root, node, data);
+                      }
+                    }
+                  },
+                ),
+                h(
+                  "Icon",
+                  {
+                    props: {
+                      type: "md-arrow-round-up"
+                    },
+                    on: {
+                      click: e => {
+                        e.stopPropagation();
+                        this.moveUp(root, node, data);
+                      }
+                    }
+                  },
+                ),
+                h(
+                  "Icon",
+                  {
+                    props: {
+                      type: "md-arrow-round-down"
+                    },
+                    on: {
+                      click: e => {
+                        e.stopPropagation();
+                        this.moveDown(root, node, data);
+                      }
+                    }
+                  },
+                ),
+                h(
+                  "Icon",
+                  {
+                    props: {
+                      type: "md-create"
+                    },
+                    on: {
+                      click: e => {
+                        e.stopPropagation();
+                        this.editClick(node, data);
+                      }
+                    }
+                  },
+                )
+              ]
+            )
+          ]
+        );
+      },
+      // 添加节点
+      append(data, value) {
+        const children = data.children || [];
+        children.push({
+          title: value,
+          order: children.length,
+          children: [],
+          expand: true
+        });
+        this.$set(data, "children", children);
+        console.log(data);
+      },
+      // 删除节点
+      remove(root, node, data) {
+        const parentKey = root.find(el => el === node).parent;
+        const parent = root.find(el => el.nodeKey === parentKey).node;
+        const index = parent.children.indexOf(data);
+        parent.children.splice(index, 1);
+      },
+      // 点击编辑
+      editClick(node, data) {
+        this.currentNode = data;
+        this.editFlag = true;
+        this.editValue = "";
+      },
+      //添加节点 弹出输入框
+      appendClick(data) {
+        this.currentNode = data;
+        this.modalFlag = true;
+        this.inputValue = "";
+        console.log(this.common.guid());
+      },
+      // 确认添加节点
+      handleAddNode() {
+        if (this.inputValue != "") {
+          this.append(this.currentNode, this.inputValue);
+        } else {
+          this.modalFlag = false;
+        }
+      },
+      // 修改节点
+      handleUpdateNode() {
+        if (this.editValue != "") {
+          this.currentNode.title = this.editValue;
+        } else {
+          this.editFlag = false;
+        }
+      },
+      // 标题点击收缩展开
+      titleClick(root, node, data, event) {
+        //const parentKey = root.find(el => el === node).parent;
+        //const parent = root.find(el => el.nodeKey === parentKey).node;
+        //const index = parent.children.indexOf(data);
+        //let list = document.getElementsByClassName('singleClass');
+        ////for(let i=0;i<list.length;i++){
+        ////  list[i].style.backgroundColor="transparent";
+        ////}
+        //  this.currentLiNode = node;
+        //  //event.currentTarget.style.backgroundColor = "rgba(225, 224, 224, 0.18)";
+        data.expand = !data.expand;
+      },
+
+      // 根目录点击事件
+      rootClick(data) {
+        data.expand = !data.expand;
+      },
+      // 上移章节操作
+      moveUp(root, node, data) {
+        const parentKey = root.find(el => el === node).parent;
+        const parent = root.find(el => el.nodeKey === parentKey).node;
+        const index = parent.children.indexOf(data);
+        const nodeIndex = root.indexOf(node);
+        let currentTitle = data.title;
+        let currentExpand = data.expand;
+        let currentChildren = data.children || [];
+        let preChildren = (parent.children[index - 1]) ? (parent.children[index - 1]).children : [];
+        if (index != 0) {
+          data.title = parent.children[index - 1].title;
+          parent.children[index - 1].title = currentTitle;
+          parent.children[index - 1].expand = currentExpand;
+          data.children = preChildren;
+          data.expand = parent.children[index - 1].expand;
+          parent.children[index - 1].children = currentChildren;
+        }
+      },
+      // 下移章节操作
+      moveDown(root, node, data) {
+        const parentKey = root.find(el => el === node).parent;
+        const parent = root.find(el => el.nodeKey === parentKey).node;
+        const index = parent.children.indexOf(data);
+        let currentTitle = data.title;
+        let currentChildren = data.children || [];
+        let nextChildren = (parent.children[index + 1]) ? (parent.children[index + 1]).children : [];
+        if (index != parent.children.length - 1) {
+          data.title = parent.children[index + 1].title;
+          data.children = nextChildren;
+          parent.children[index + 1].title = currentTitle;
+          parent.children[index + 1].children = currentChildren;
+        }
+      },
+      // 更多操作
+      handleTools(root, node, data, event) {
+        let toolsDom = event.currentTarget.nextElementSibling;
+        const parentKey = root.find(el => el === node).parent;
+        const parent = root.find(el => el.nodeKey === parentKey).node;
+        const index = parent.children.indexOf(data);
+        let list = document.getElementsByClassName("tools");
+        let cFlag = toolsDom.style.display;
+        for (let i = 0; i < list.length; i++) {
+          list[i].style.display = "none";
+        }
+        // 判断TOOL显示与隐藏
+        if (cFlag == "none") {
+          toolsDom.style.display = "inline-flex";
+          toolsDom.classList.add("animated");
+          toolsDom.classList.add("slideInDown");
+        } else {
+          toolsDom.style.display = "none";
+        }
+      },
+      // 鼠标从工具条移开的时候隐藏
+      hideTools(event) {
+        event.currentTarget.style.display = "none";
+      },
+      handleLiOver(event) {
+        event.currentTarget.lastElementChild.style.display = "block";
+        event.currentTarget.style.backgroundColor = "rgba(255, 255, 255, 0.68)";
+        event.currentTarget.style.border = "1px solid #000";
+      },
+      handleLiLeave(node, event) {
+        event.currentTarget.lastElementChild.style.display = "none";
+        if (this.currentLiNode.nodeKey != node.nodeKey) {
+          event.currentTarget.style.backgroundColor = "transparent";
+          event.currentTarget.style.border = "0";
+        }
+      },
+      // 添加教材
+      handleAddBook() {
+        this.$api.FindPeriods({}).then(res => {
+          this.periodList = res.result.data;
+          this.periodSelect = this.periodList[0].rowKey;
+          this.periodName = this.periodList[0].name;
+          let Pcode = {
+            value: this.periodList[0].rowKey,
+            label: this.periodList[0].name
+          }
+          this.periodChange(Pcode);
+        })
+        this.addBookFlag = true;
+      },
+
+      // 学段选择变化
+      periodChange(val) {
+        this.$api.FindSubjects({ Pcode: val.value }).then(res => {
+          if (res.result.data.length > 0) {
+            this.subjectList = res.result.data;
+            this.subjectSelect = this.subjectList[0].rowKey;
+            this.periodName = val.label;
+            let Pcode = {
+              value: this.subjectList[0].rowKey,
+              label: this.subjectList[0].name
+            }
+            this.subjectChange(Pcode);
+          }
+        })
+      },
+      // 学科选择变化
+      subjectChange(val) {
+        this.$api.FindEditions({ Pscode: val.value }).then(res => {
+          if (res.result.data.length > 0) {
+            this.versionList = res.result.data;
+            this.versionSelect = this.versionList[0].rowKey;
+            this.subjectName = val.label;
+            let Pcode = {
+              value: this.versionList[0].rowKey,
+              label: this.versionList[0].name
+            }
+            this.versionChange(Pcode);
+          }
+        })
+      },
+      // 版本选择变化
+      versionChange(val) {
+        this.$api.FindTerms({ Psecode: val.value }).then(res => {
+          this.gradeList = res.result.data;
+          this.gradeSelect = this.gradeList.length > 0 ? this.gradeList[0].rowKey : "无";
+          this.versionName = val.label;
+          let Pcode = {
+            value: this.gradeList.length > 0 ? this.gradeList[0].rowKey : "",
+            label: this.gradeList.length > 0 ? this.gradeList[0].name : ""
+          }
+          if (this.gradeList.length > 0) {
+            this.gradeChange(Pcode);
+          }
+        })
+      },
+      //册别选择变化
+      gradeChange(val) {
+        this.gradeName = val.label ? val.label : "";
+      },
+      // 确认添加教材返回教材名称
+      handleAddConfirm() {
+        let periodRowKeys = [];
+        let perioArr = this.periodList;
+        for (let item of perioArr) {
+          periodRowKeys.push(item.rowKey);
+        }
+        let bookName = this.periodName + this.subjectName + this.versionName + this.gradeName;
+        this.treeData[0].title = bookName;
+      }
+    },
+  };
+</script>
+<style>
+  .tree-main {
+    margin-left: 5%;
+    width: 90%;
+  }
+
+  .ivu-icon-ios-paper-outline {
+    font-size: 16px;
+  }
+
+  .ivu-select {
+    width: 80% !important;
+  }
+
+  .slideSelect .ivu-select-selection {
+    height: 40px;
+    background: #d8d8d870;
+    border: 1px solid #808080;
+  }
+
+  .slideSelect, .slideSelect .ivu-icon {
+    color: rgba(255,255,255,.8);
+  }
+
+  .ivu-select-single .ivu-select-selection .ivu-select-selected-value {
+    height: 40px;
+    line-height: 40px;
+    font-size: 14px;
+  }
+  /* .ivu-tree ul li {
+    margin: 18px 0;
+  } */
+  .ivu-tree ul {
+    font-size: 14px;
+  }
+
+  .ivu-tree ul li {
+    margin:8px 0 !important;
+  }
+
+  .ivu-tree .ivu-tree-arrow {
+    width: 2%;
+  }
+
+  .ivu-input-wrapper {
+    width: 80% !important;
+  }
+
+  .modelRow {
+    margin: 20px;
+    font-size: 14px;
+  }
+
+  .tools {
+    position: absolute;
+    right: 60px;
+    display: inline-flex;
+    z-index: 999;
+  }
+
+    .tools .ivu-icon {
+      margin-right: 15px;
+      font-size: 16px;
+      font-weight:200;
+      color: #808080;
+    }
+
+  .btn_more {
+    background: #fff;
+    border: 1px solid rgb(248,248,248);
+  }
+
+  .animated {
+    animation-duration: 0.5s;
+  }
+
+  @-webkit-keyframes slideInDown {
+    from {
+      -webkit-transform: translate3d(0,-10%, 0);
+      transform: translate3d(0, -10%, 0) !important;
+      visibility: visible;
+    }
+
+    to {
+      -webkit-transform: translate3d(0, 0%, 0);
+      transform: translate3d(0, 0%, 0);
+    }
+  }
+
+  @keyframes slideInDown {
+    from {
+      -webkit-transform: translate3d(0, -10%, 0);
+      transform: translate3d(0, -10%, 0) !important;
+      visibility: visible;
+    }
+
+    to {
+      -webkit-transform: translate3d(0, 0%, 0);
+      transform: translate3d(0, 0%, 0);
+    }
+  }
+
+  .slideInDown {
+    -webkit-animation-name: slideInDown;
+    animation-name: slideInDown;
+  }
+
+  .singleClass {
+    display: inline-flex !important;
+    flex-direction: row;
+    align-items: center;
+    height: 40px;
+  }
+
+  .btn-addClass {
+    width: 16%;
+    padding: 10px 6px !important;
+  }
+
+  .ivu-tabs-nav-scroll {
+    display: flex;
+    justify-content: center;
+  }
+
+  .addBookArea .ivu-select {
+    width: 80% !important;
+    margin-left: 30px;
+  }
+
+  .addBookArea .ivu-select-single .ivu-select-selection {
+    height: 32px;
+  }
+
+  .addBookArea .ivu-row {
+    margin: 30px 20px;
+  }
+
+  .addBookArea .ivu-select-selected-value {
+    height: 32px !important;
+    line-height: 32px !important;
+    font-size: 12px !important;
+  }
+
+  .ivu-tabs {
+    overflow: unset;
+  }
+</style>

+ 14 - 0
TEAMModelOS/ClientApp/router/routes.js

@@ -53,5 +53,19 @@ export const routes = [
         component: resolve => require(['@/view/syllabus/BaseKnowPoint.vue'], resolve),
       }
     ]
+  },
+  {
+    path: '/SAK',
+    component: resolve => require(['@/view/sak/Syllabus.vue'], resolve), //路由懒加载
+    children: [
+      {
+        path: '/',
+        component: resolve => require(['@/common/SyTree.vue'], resolve),
+      },
+      {
+        path: '/BaseKnowPoint',
+        component: resolve => require(['@/view/syllabus/BaseKnowPoint.vue'], resolve),
+      }
+    ]
   }
 ]

+ 2 - 2
TEAMModelOS/ClientApp/view/index.vue

@@ -149,8 +149,8 @@
               that.$Message.success(this.$t('index.loginSuc'));
             }
             let decode = that.$jwtDecode(res.result.data.jwtToken.access_token);//解析返回的token
-            that.roleList = decode.role.split(',');
-            that.changeLoginRoles(decode.role.split(','));//身份替换
+            that.roleList = decode.role;
+            that.changeLoginRoles(decode.role);//身份替换
             localStorage.setItem('token', token);
             localStorage.setItem('username', decode.name);
             localStorage.setItem('decodeData', JSON.stringify(decode));

+ 79 - 0
TEAMModelOS/ClientApp/view/sak/Syllabus.vue

@@ -0,0 +1,79 @@
+<template>
+  <div class="index">
+     <div class="sak-header">
+       <Headers></Headers>
+     </div>
+     <div class="sak-main center">
+       <div class="sak-left">
+         <Syllabus></Syllabus>
+       </div>
+       <div class="sak-right">
+         <KnowPoint></KnowPoint>
+       </div>
+     </div>
+  </div>
+</template>
+<script>
+  import Headers from '@/common/headers.vue'
+  import Syllabus from '@/common/Syllabus.vue'
+  import KnowPoint from '@/common/KnowPoint.vue'
+  export default {
+    name: "app",
+    components: {
+      Headers: Headers,
+      Syllabus: Syllabus,
+      KnowPoint: KnowPoint
+    },
+    data() {
+      return {
+        schoolName: "",
+        username: "",
+        activeIndex: sessionStorage.getItem('kIndex') || 0
+      }
+    },
+    created() {
+    
+    },
+    methods: {
+
+    },
+    mounted() {
+      
+    }
+  }
+</script>
+<style scoped>
+  .index {
+    position: relative;
+    width: 100%;
+    height:100%;
+    overflow-y:hidden;
+    min-width: 1366px;
+    background: #fff;
+    -moz-user-select: none; /*火狐 firefox*/
+    -webkit-user-select: none; /*webkit浏览器*/
+    -ms-user-select: none; /*IE10+*/
+    user-select: none;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+  }
+  .sak-header{
+     width:100%;
+     height:60px;
+  }
+  .sak-main {
+    width: 100%;
+    height: 100%;
+  }
+
+  .sak-left {
+    width: 60%;
+    height: 100%;
+  }
+  .sak-right {
+    width: 40%;
+    height: 100%;
+  }
+
+</style>

+ 12 - 3
TEAMModelOS/Controllers/Core/BaseController.cs

@@ -7,11 +7,13 @@ using System.Threading.Tasks;
 using TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper;
 using TEAMModelOS.SDK.Extension.JwtAuth.Models;
 using TEAMModelOS.SDK.Context.Constant.Common;
+using System.Security.Claims;
+
 namespace TEAMModelOS.Controllers.Core
 {
     public class BaseController : Controller
     {
-        public   string GetLoginUser(string claimType)
+        public List<string> GetLoginUser(string claimType)
         {
             var tokenHeader = "";
             HttpRequest request = HttpContext.Request;
@@ -28,11 +30,18 @@ namespace TEAMModelOS.Controllers.Core
             }
             if (string.IsNullOrEmpty(tokenHeader))
             {
-                return "";
+                return null ;
             }
             ClaimModel claimModel = JwtHelper.SerializeJWT(tokenHeader);
             claimModel.Claim.TryGetValue(claimType, out var claimValue);
-            return claimValue;
+            List<string> claimValues = new List<string>();
+            foreach (Claim claim in claimModel.Claims) {
+                if(claim.Type.Equals(claimType))
+                {
+                    claimValues.Add(claim.Value);
+                }
+            }
+            return claimValues;
         }
     }
 }

+ 11 - 7
TEAMModelOS/Controllers/Core/RoleController.cs

@@ -1,4 +1,5 @@
 using IdentityModel;
+using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using System;
@@ -8,6 +9,7 @@ using System.Threading.Tasks;
 using TEAMModelOS.Model.Core.Models;
 using TEAMModelOS.SDK.Extension.DataResult.JsonRpcRequest;
 using TEAMModelOS.SDK.Extension.DataResult.JsonRpcResponse;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
 using TEAMModelOS.Service.Core.Interfaces;
 
 namespace TEAMModelOS.Controllers.Core
@@ -17,6 +19,7 @@ namespace TEAMModelOS.Controllers.Core
     /// </summary>
     [Route("api/[controller]")]
     [ApiController]
+    [Authorize]
     public class RoleController : BaseController
     {
         private IRoleService _roleSeservice;
@@ -37,15 +40,16 @@ namespace TEAMModelOS.Controllers.Core
         public async Task<BaseJosnRPCResponse> GetLoginRoles(JosnRPCRequest<Dictionary<string, object>> request)
         {
             JsonRPCResponseBuilder builder = JsonRPCResponseBuilder.custom();
-            string rolecodes = GetLoginUser(JwtClaimTypes.Role);
+            List<string> rolecodes = GetLoginUser(JwtClaimTypes.Role);
             List<Role> roles = new List<Role>();
-            string[] codes = rolecodes.Split(",");
-            foreach (string code in codes)
-            {
-                Role role = await _roleSeservice.FindRoleByRowKey(code);
-                if (role != null&& !string.IsNullOrEmpty(role.RowKey))
+            if (rolecodes.IsNotEmpty()) {
+                foreach (string code in rolecodes)
                 {
-                    roles.Add(role);
+                    Role role = await _roleSeservice.FindRoleByRowKey(code);
+                    if (role != null && !string.IsNullOrEmpty(role.RowKey))
+                    {
+                        roles.Add(role);
+                    }
                 }
             }
             return builder.Data(roles).build();

+ 1 - 0
TEAMModelOS/Startup.cs

@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Http.Features;
+using Microsoft.AspNetCore.Identity;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.SpaServices.Webpack;
 using Microsoft.Extensions.Configuration;

+ 1 - 1
TEAMModelOS/appsettings.Development.json

@@ -9,7 +9,7 @@
   "AllowedHosts": "*",
   "Azure": {
     "Table": {
-      "ConnectionString": "AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;DefaultEndpointsProtocol=http;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;",
+      "ConnectionString": "AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;DefaultEndpointsProtocol=http;BlobEndpoint=http://192.168.8.192:10000/devstoreaccount1;QueueEndpoint=http://192.168.8.192:10001/devstoreaccount1;TableEndpoint=http://192.168.8.192:10002/devstoreaccount1;",
       "AzureTableDialect": ""
     },
     "Blob": {