瀏覽代碼

Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd

zhouj1203@hotmail.com 4 年之前
父節點
當前提交
4119da1a36
共有 86 個文件被更改,包括 3577 次插入1818 次删除
  1. 4 1
      TEAMModelOS.SDK/DI/DingDing/DingDing.cs
  2. 4 1
      TEAMModelOS.SDK/Models/Cosmos/Common/Bloblog.cs
  3. 13 7
      TEAMModelOS.SDK/Models/Cosmos/Common/Inner/SyllabusTree.cs
  4. 14 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Syllabus.cs
  5. 12 0
      TEAMModelOS.SDK/Models/Cosmos/Common/TmdInfo.cs
  6. 1 16
      TEAMModelOS.SDK/Models/Cosmos/Common/Volume.cs
  7. 0 111
      TEAMModelOS.SDK/Models/Cosmos/Teacher/Favorite.cs
  8. 127 0
      TEAMModelOS.SDK/Models/Cosmos/Teacher/Share.cs
  9. 73 9
      TEAMModelOS/ClientApp/src/api/blob.js
  10. 6 1
      TEAMModelOS/ClientApp/src/api/schoolSetting.js
  11. 62 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/event-list-new.css
  12. 76 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/event-list-new.less
  13. 97 55
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-test.css
  14. 5 5
      TEAMModelOS/ClientApp/src/common/BaseAreaPicker.vue
  15. 5 31
      TEAMModelOS/ClientApp/src/common/BaseLayout.less
  16. 73 23
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  17. 10 1
      TEAMModelOS/ClientApp/src/common/BaseNotification.vue
  18. 0 1
      TEAMModelOS/ClientApp/src/common/BaseSelectSchool.vue
  19. 63 8
      TEAMModelOS/ClientApp/src/common/UploadModal.vue
  20. 41 30
      TEAMModelOS/ClientApp/src/components/app-root.vue
  21. 1 3
      TEAMModelOS/ClientApp/src/components/evaluation/ExerciseList.vue
  22. 1 1
      TEAMModelOS/ClientApp/src/components/public/frontEndMain/Index.vue
  23. 2 4
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/StudentScore.vue
  24. 152 52
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue
  25. 1 1
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperView.vue
  26. 70 7
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue
  27. 6 5
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseList.vue
  28. 0 96
      TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue
  29. 4 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/stuAccount.js
  30. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/system.js
  31. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/teachContent.js
  32. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/updModal.js
  33. 16 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/settings.js
  34. 4 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/stuAccount.js
  35. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/studentWeb.js
  36. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/system.js
  37. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/teachContent.js
  38. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/totalAnalysis.js
  39. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/updModal.js
  40. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/evaluation.js
  41. 23 7
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/settings.js
  42. 4 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/stuAccount.js
  43. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/system.js
  44. 3 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachContent.js
  45. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/totalAnalysis.js
  46. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/updModal.js
  47. 992 0
      TEAMModelOS/ClientApp/src/static/countries.js
  48. 1 1
      TEAMModelOS/ClientApp/src/store/module/serviceDriveAuth.js
  49. 1 1
      TEAMModelOS/ClientApp/src/store/module/studentWeb.js
  50. 0 19
      TEAMModelOS/ClientApp/src/view/Home.vue
  51. 51 31
      TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue
  52. 2 1
      TEAMModelOS/ClientApp/src/view/evaluation/bank/ExerciseList.vue
  53. 3 3
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseFilter.vue
  54. 5 1
      TEAMModelOS/ClientApp/src/view/evaluation/index/index.vue
  55. 8 10
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue
  56. 10 56
      TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkData.vue
  57. 8 0
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.less
  58. 3 1
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue
  59. 1 1
      TEAMModelOS/ClientApp/src/view/questionnaire/ManageQuestionnaire.less
  60. 2 2
      TEAMModelOS/ClientApp/src/view/schoolmgmt/ClassroomSetting/ClassroomSetting.less
  61. 4 4
      TEAMModelOS/ClientApp/src/view/schoolmgmt/ClassroomSetting/ClassroomSetting.vue
  62. 335 395
      TEAMModelOS/ClientApp/src/view/serviceDriveAuth/SubComponents/HiteachAuthList.vue
  63. 202 209
      TEAMModelOS/ClientApp/src/view/serviceDriveAuth/SubComponents/ServiceList.vue
  64. 80 19
      TEAMModelOS/ClientApp/src/view/settings/BaseApplyForm.vue
  65. 11 1
      TEAMModelOS/ClientApp/src/view/settings/Index.less
  66. 2 2
      TEAMModelOS/ClientApp/src/view/settings/Index.vue
  67. 12 10
      TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.css
  68. 5 6
      TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.less
  69. 6 23
      TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.vue
  70. 123 0
      TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.css
  71. 6 0
      TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.less
  72. 2 1
      TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.vue
  73. 1 1
      TEAMModelOS/ClientApp/src/view/student-account/ImportStudent.vue
  74. 3 7
      TEAMModelOS/ClientApp/src/view/student-account/Index.vue
  75. 5 5
      TEAMModelOS/ClientApp/src/view/student-web/App.vue
  76. 1 1
      TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.less
  77. 14 5
      TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.vue
  78. 103 47
      TEAMModelOS/ClientApp/src/view/teachcontent/ResBelong.vue
  79. 17 2
      TEAMModelOS/ClientApp/src/view/teachcontent/index.less
  80. 239 31
      TEAMModelOS/ClientApp/src/view/teachcontent/index.vue
  81. 1 1
      TEAMModelOS/ClientApp/src/view/vote/ManageVote.less
  82. 21 8
      TEAMModelOS/Controllers/Core/BlobController.cs
  83. 19 2
      TEAMModelOS/Controllers/Core/CoreController.cs
  84. 182 154
      TEAMModelOS/Controllers/Syllabus/ShareController.cs
  85. 103 267
      TEAMModelOS/Controllers/Syllabus/SyllabusController.cs
  86. 2 4
      TEAMModelOS/Controllers/Syllabus/VolumeController.cs

+ 4 - 1
TEAMModelOS.SDK/DI/DingDing/DingDing.cs

@@ -99,7 +99,10 @@ namespace TEAMModelOS.SDK.DI
         [Description("82aba2fccfa8442c575db3ac0442fa5aea90cd7574bb9a71d5abf210ea72a3aa,SEC3f38eca87cd4fd10505d136f91071a2e8b14cd863bd6bbafb24c612fc751a59a")]
         成都开发測試群組,
         [Description("1a316ce4edc2db88231d40d80072b00f2751d7d9e2e5871c5dc061885b01c48d,SECff60201ac9b219943b9f8fc397fda1a617d0cbc140850f5ea9cb4f131479d39a")]
-        醍摩豆服務運維群組
+        醍摩豆服務運維群組,
+        [Description("a83ea4ead63bf1b4e087723b3a7ccdf7f4c96708a22493f489bb928999f50d87,SECf1d22db7d00580dc7c0e597e31112a25ae1025500fc998b5b30961d91e115271")]
+        AI智慧學校申請通知群
+
     }
 
 

+ 4 - 1
TEAMModelOS.SDK/Models/Cosmos/Common/Bloblog.cs

@@ -13,10 +13,13 @@ namespace TEAMModelOS.SDK.Models
         public string url { get; set; }
         public long  time { get; set; }
         public long  size { get; set; }
-        public string period { get; set; }
+        public List<string> periodId { get; set; } = new List<string>() { "" };
+        public List<string> subjectId { get; set; } = new List<string>() { "" };
+        public List<string> gradeId { get; set; } = new List<string>() { "" };
         /// <summary>
         /// audio 音频,video 视频 ,doc文档,image图片,other 其他,res教材,thum缩略图
         /// </summary>
         public string type { get; set; }
+
     }
 }

+ 13 - 7
TEAMModelOS.SDK/Models/Cosmos/Common/Inner/SyllabusTree.cs

@@ -10,14 +10,20 @@ namespace TEAMModelOS.SDK.Models
         }
         public List<SyllabusTree> children { get; set; }
     }
-    public class SyllabusTreeNode{
-        public string id { get; set; }
-       // public string code { get; set; }
-        public string scope { get; set; }
-        public SyllabusTreeNode() {
+    public class SyllabusTreeNode {
+
+        public SyllabusTreeNode(){
             trees = new List<SyllabusTree>();
         }
-        public List<SyllabusTree> trees { get; set; }
-    }
+        public string  id { get; set; }
+        /// <summary>
+        /// 册别的id
+        /// </summary>
+        public string volumeId { get; set; }
+       // public string code { get; set; }
+        public string scope { get; set; }
+        public  List<SyllabusTree>  trees  { get; set; }
 
+        public List<SyllabusAuth> auth { get; set; } = new List<SyllabusAuth>();
+    }
 }

+ 14 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Syllabus.cs

@@ -20,5 +20,19 @@ namespace TEAMModelOS.SDK.Models
         [Required(ErrorMessage = "{0} 必须填写")]
         public List<Tnode> children { get; set; }
         public string volumeId { get; set; }
+        public List<SyllabusAuth> auth { get; set; }
+        public string scope { get; set; }
+}
+
+    /// <summary>
+    /// 只要创建课纲的creatorId 才能编辑课纲的分享,共编权限 25600 74200  27500 2000
+    /// ,共编者 谁创建的节点只能谁删除,而且删除时能删除子节点(包含不是自己创建的)。
+    /// </summary>
+    public class SyllabusAuth
+    {
+        public string tmdid { get; set; }
+        public string tmdname { get; set; }
+        public bool coedit { get; set; }
+        public bool share { get; set; }
     }
 }

+ 12 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/TmdInfo.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models
+{
+    public  class TmdInfo
+    {
+        public string tmdid { get; set; }
+        public string tmdname { get; set; }
+    }
+}

+ 1 - 16
TEAMModelOS.SDK/Models/Cosmos/Common/Volume.cs

@@ -82,22 +82,7 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
         /// </summary>
         [Required(ErrorMessage = "scope 必须设置")]
         public string scope { get; set; }
-        public List<SyllabusAuth> auth { get; set; } = new List<SyllabusAuth>();
+       
     }
 
-    /// <summary>
-    /// 只要创建课纲的creatorId 才能编辑课纲的分享,共编权限 25600 74200  27500 2000
-    /// ,共编者 谁创建的节点只能谁删除,而且删除时能删除子节点(包含不是自己创建的)。
-    /// </summary>
-    public class SyllabusAuth
-    {
-        public string tmdid { get; set; }
-        public string name { get; set; }
-        public bool coedit { get; set; }
-        public bool share { get; set; }
-        /// <summary>
-        ///分享的节点 all  或者節點id
-        /// </summary>
-        public List<string> snodes { get; set; } = new List<string>();
-    }
 }

+ 0 - 111
TEAMModelOS.SDK/Models/Cosmos/Teacher/Favorite.cs

@@ -36,115 +36,4 @@ namespace TEAMModelOS.SDK.Models.Cosmos
         [Required(ErrorMessage = "引用来源课纲code 必须设置")]
         public string fromCode { get; set; }
     }
-
-    /*
-     {
-        "id":"课纲册别id",
-        "code":"Share-接收者tmdid",
-        "issuer":"分享者tmdid",
-        "createTime":分享时间,
-        "scode":"引用来源课纲册别code",
-        "scope":"school/private",
-        "school":"hbcn",
-        "issuer":"颁发权限的id"
-    }
-     */
-    /// <summary>
-    /// 主动分享给谁, 分享功能只会发生在个人课纲中
-    /// </summary>
-    public class Share : CosmosEntity {
-        public Share(){
-            pk = "Share";
-        }
-
-        public string scode { get; set; }
-        /// <summary>
-        /// 权限颁发者
-        /// </summary>
-        public string issuer { get; set; }
-        public long  createTime { get; set; }
-        /// <summary>
-        /// 学校编码或教师tmdid
-        /// </summary>
-        [Required(ErrorMessage = "school 必须设置")]
-        public string school { get; set; }
-        /// <summary>
-        /// school|private
-        /// </summary>
-        [Required(ErrorMessage = "scope 必须设置")]
-        public string scope { get; set; }
-        /// <summary>
-        /// 共编
-        /// </summary>
-        public bool coedit { get; set; }
-        /// <summary>
-        /// 分享
-        /// </summary>
-        public bool share { get; set; }
-        /// <summary>
-        /// 课纲名称
-        /// </summary>
-        public string sname { get; set; }
-    }
-         
-    /// <summary>
-    /// 主动分享给谁,当接收者接收并完成相关资源复制后则删除本条数据。
-    /// </summary>
-    public class ShareData
-    {
-        /// <summary>
-        /// 学校编码
-        /// </summary>
-        [Required(ErrorMessage = "school 必须设置")]
-        public string school { get; set; }
-        /// <summary>
-        /// school|private
-        /// </summary>
-        [Required(ErrorMessage = "scope 必须设置")]
-        public string scope { get; set; }
-        /// <summary>
-        /// add/edit/del
-        /// </summary>
-        [Required(ErrorMessage = "opt 必须设置")]
-        public string opt { get; set; }
-
-        [Required(ErrorMessage = "tmdid 必须设置")]
-        public string tmdid { get; set; }
-        /// <summary>
-        /// tmdname
-        /// </summary>
-        public string name { get; set; }
-        /// <summary>
-        /// 课纲册别的id
-        /// </summary>
-        [Required(ErrorMessage = "sid 必须设置")]
-        public string sid { get; set; }
-        /// <summary>
-        /// 课纲册别的分区键
-        /// </summary>
-        [Required(ErrorMessage = "socde 必须设置")]
-        public string scode { get; set; }
-        /// <summary>
-        /// 课纲册别的名称
-        /// </summary>
-        [Required(ErrorMessage = "sname 必须设置")]
-        public string sname { get; set; }
-        /// <summary>
-        /// 共编权限
-        /// </summary>
-        public bool coedit { get; set; } = false;
-        /// <summary>
-        /// 分享权限
-        /// </summary>
-        public bool share { get; set; } = false;
-        /// <summary>
-        /// 分享的节点 all  或者節點id
-        /// </summary>
-        public List<string> snodes { get; set; } = new List<string>();
-        /// <summary>
-        /// 共编 分享权限颁发者
-        /// </summary>
-        [Required(ErrorMessage = "issuer 必须设置")]
-        public string issuer { get; set; }
-    }
 }

+ 127 - 0
TEAMModelOS.SDK/Models/Cosmos/Teacher/Share.cs

@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models
+{
+    /*
+     {
+        "id":"课纲册别id",
+        "code":"Share-接收者tmdid",
+        "issuer":"分享者tmdid",
+        "createTime":分享时间,
+        "scode":"引用来源课纲册别code",
+        "scope":"school/private",
+        "school":"hbcn",
+        "issuer":"颁发权限的id"
+    }
+     */
+    /// <summary>
+    /// 主动分享给谁, 分享功能只会发生在个人课纲中
+    /// </summary>
+    public class Share : CosmosEntity
+    {
+        /// <summary>
+        /// id 为章节id, code为Share-tmdid
+        /// </summary>
+        public Share()
+        {
+            pk = "Share";
+        }
+        /// <summary>
+        /// 权限颁发者
+        /// </summary>
+        public string issuer { get; set; }
+        public long createTime { get; set; }
+        /// <summary>
+        /// 学校编码或教师tmdid
+        /// </summary>
+        [Required(ErrorMessage = "school 必须设置")]
+        public string school { get; set; }
+        /// <summary>
+        /// school|private
+        /// </summary>
+        [Required(ErrorMessage = "scope 必须设置")]
+        public string scope { get; set; }
+        /// <summary>
+        /// 共编
+        /// </summary>
+        public bool coedit { get; set; }
+        /// <summary>
+        /// 分享
+        /// </summary>
+        public bool share { get; set; }
+        /// <summary>
+        /// 册别id
+        /// </summary>
+        public string volumeId { get; set; }
+        /// <summary>
+        /// 课纲章节的name
+        /// </summary>
+        [Required(ErrorMessage = "syllabusName 必须设置")]
+        public string syllabusName { get; set; }
+        /// <summary>
+        /// 册别名称
+        /// </summary>
+        public string volumeName { get; set; }
+    }
+    /// <summary>
+    /// 主动分享给谁,当接收者接收并完成相关资源复制后则删除本条数据。
+    /// </summary>
+    public class ShareData
+    {
+        /// <summary>
+        /// 学校编码
+        /// </summary>
+        [Required(ErrorMessage = "school 必须设置")]
+        public string school { get; set; }
+        /// <summary>
+        /// school|private
+        /// </summary>
+        [Required(ErrorMessage = "scope 必须设置")]
+        public string scope { get; set; }
+        /// <summary>
+        /// add/edit/del
+        /// </summary>
+        [Required(ErrorMessage = "opt 必须设置")]
+        public string opt { get; set; }
+
+        [Required(ErrorMessage = "tmdid 必须设置")]
+        public List<TmdInfo> tmdInfo { get; set; } = new List<TmdInfo>();
+        
+        /// <summary>
+        /// 共编权限
+        /// </summary>
+        public bool coedit { get; set; } = false;
+        /// <summary>
+        /// 分享权限
+        /// </summary>
+        public bool share { get; set; } = false;
+        /// <summary>
+        /// 课纲章节的id
+        /// </summary>
+        [Required(ErrorMessage = "syllabusId 必须设置")]
+        public string syllabusId { get; set; }
+        /// <summary>
+        /// 课纲章节的name
+        /// </summary>
+        [Required(ErrorMessage = "syllabusName 必须设置")]
+        public string syllabusName { get; set; }
+        /// <summary>
+        /// 册别名称
+        /// </summary>
+        public string volumeName { get; set; }
+        /// <summary>
+        /// 册别id
+        /// </summary>
+        public string volumeId { get; set; }
+        /// <summary>
+        /// 共编 分享权限颁发者
+        /// </summary>
+        [Required(ErrorMessage = "issuer 必须设置")]
+        public string issuer { get; set; }
+    }
+
+
+}

+ 73 - 9
TEAMModelOS/ClientApp/src/api/blob.js

@@ -1,10 +1,26 @@
 import { fetch, post } from '@/api/http'
+import { GLOBAL } from '@/static/Global.js';
+//获取文件后缀和类型
+function getExAndType(fileName) {
+    let ex = fileName.substring(fileName.lastIndexOf('.') + 1)
+    let type = 'other'
+    ex = ex.toUpperCase()
+    for (let key in GLOBAL.CONTENT_TYPES) {
+        if (GLOBAL.CONTENT_TYPES[key].indexOf(ex) != -1) {
+            type = key
+            break
+        }
+    }
+    return {
+        ex, type
+    }
+}
 export default {
-    getBlobSAS: function(data) {
+    getBlobSAS: function (data) {
         return post('/api/File/getBlobSAS', data)
     },
     //最开始使用的blob授权API
-    getContainerSAS: function(data) {
+    getContainerSAS: function (data) {
         return post('/api/File/getContainerSAS', data)
     },
     //获取blob容器读写创建
@@ -12,31 +28,79 @@ export default {
         return post('/blob/sas-rcwld', data)
     },
     //获取blob容器只读创建
-    blobSasR: function(data) {
+    blobSasR: function (data) {
         return post('/blob/sas-r', data)
     },
     //单文件只读权限
-    urlSasR: function(data) {
+    urlSasR: function (data) {
         return post('/blob/sas-url-r', data)
     },
     //获取容器空间
     getContainerSize: function (data) {
         return post('/blob/get-blobsize', data)
     },
-	// 删除blob指定目录下的所有文件
-	deletePrefix: function (data) {
+    // 删除blob指定目录下的所有文件
+    deletePrefix: function (data) {
         return post('/blob/delete-prefix', data)
     },
     // 批量删除blob
-	deleteBlobs: function (data) {
+    deleteBlobs: function (data) {
         return post('/blob/delete-blobs', data)
     },
     // 上传文件之前需要先检查文件是否存在
-	checkBlobs: function (data) {
+    checkBlobs: function (data) {
         return post('/blob/check-blobsize', data)
     },
     // 上传文件之后需要更新blob空间
-	updateSize: function (data) {
+    updateSize: function (data) {
         return post('/blob/update-blobsize', data)
+    },
+    /**
+     * 上传文件之后保存文件的描述信息
+     * opt: add 更新
+     * opt: del 删除
+     **/
+    upsertBlobInfo: function (data) {
+        return post('/blob/bloblog-opt', data)
+    },
+    /**
+     * 查询资源信息
+     * 这里统一将返回数据处理成原来前端直接listBlob返回的数据格式
+     * @returns 
+     */
+    listBlobInfo: function (data, host, container) {
+        return new Promise((r, j) => {
+            post('/blob/bloblog-list', data).then(
+                res => {
+                    console.log(res)
+                    let blobs = []
+                    res.bloblogs.forEach(item => {
+                        let blobName = item.url
+                        let info = getExAndType(item.url)
+                        let i = {
+                            url: host + '/' +container + '/' + item.url,
+                            blob: '/' + item.url,
+                            name: blobName.substring(blobName.lastIndexOf('/') + 1),
+                            size: item.size,
+                            createTime: item.time,
+                            extension: info.ex,
+                            type: info.type,
+                            periodId: item.periodId,
+                            subjectId: item.subjectId,
+                            gradeId: item.gradeId,
+                            id: item.id
+                        }
+                        blobs.push(i)
+                    })
+                    r(blobs)
+                },
+                err => {
+                    j(err)
+                }
+            )
+
+        })
+
+        // return post('/blob/bloblog-list', data)
     }
 }

+ 6 - 1
TEAMModelOS/ClientApp/src/api/schoolSetting.js

@@ -73,5 +73,10 @@ export default {
     //根据私有班级id集合查询班级详细信息
     getClassByIds: function (data) {
         return post('/school/classroom/name', data)
-    }
+    },
+	
+	// 申请建立学校
+	applySchool:function (data) {
+        return post('/core/apply-school', data)
+    },
 }

+ 62 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/event-list-new.css

@@ -0,0 +1,62 @@
+.list-new {
+  display: flex;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+  padding: 15px 10px 15px 25px;
+}
+.list-new:hover {
+  background: linear-gradient(-270deg, #fafafa, #d4ede1);
+  color: #03966a;
+  cursor: pointer;
+}
+.list-new-icon {
+  width: 10%;
+  margin-right: 30px;
+}
+.list-new-icon .svg-icon {
+  width: 40px;
+  height: 40px;
+}
+.list-new-test {
+  width: 70%;
+  font-weight: bolder;
+  font-size: 14px;
+  line-height: 22px;
+  margin-right: 20px;
+  clear: both;
+}
+.list-new-test .list-item-typeMark {
+  text-align: center;
+  background-color: #dfdfdf;
+  border-radius: 10px;
+  padding: 1px 10px;
+  margin: 0 8px 0 -10px;
+}
+.list-new-test .list-item-time {
+  color: #8f8787;
+  font-size: 12px;
+}
+.list-new-test .isScore {
+  float: right;
+}
+.list-new-type {
+  width: 15%;
+  display: flex;
+  justify-content: center;
+  flex-direction: column;
+}
+.list-new-type .list-new-unDone {
+  font-size: 10px;
+  font-weight: bolder;
+  padding: 5px;
+  border-radius: 4px;
+  text-align: center;
+  border: 1px solid;
+}
+.list-new-type .isAllowRetry {
+  color: #fff;
+  background-color: #64ae16;
+  border: none;
+}
+.list-new-type .isWrongPra {
+  margin-top: 10px;
+}

+ 76 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/event-list-new.less

@@ -0,0 +1,76 @@
+.list-new{
+    display: flex;
+    border-bottom: 1px solid rgba(0,0,0,.1);
+    padding: 15px 10px 15px 25px;
+
+    &:hover{
+        background: linear-gradient(-270deg, #fafafa, #d4ede1);
+        color: #03966a;
+        cursor: pointer;
+    }
+
+    &-icon{
+        width: 10%;
+        margin-right: 30px;
+
+        .svg-icon{
+            width: 40px;
+            height: 40px;
+        }
+    }
+
+    &-test{
+        width: 70%;
+        font-weight: bolder;
+        font-size: 14px;
+        line-height: 22px;
+        margin-right: 20px;
+        clear: both;
+
+        .list-item-typeMark{
+            text-align: center;
+            background-color: #dfdfdf;
+            border-radius: 10px;
+            padding: 1px 10px;
+            margin: 0 8px 0 -10px;
+        }
+
+        .list-item-time {
+            color: #8f8787;
+            font-size: 12px;
+        }
+
+        .isScore{
+            float: right;
+        }
+    }
+
+    &-type{
+        width: 15%;
+        display: flex;
+        justify-content: center;
+        flex-direction: column;
+
+        .list-new-unDone{
+            font-size: 10px;
+            font-weight: bolder;
+            // color: #fff;
+            padding: 5px;
+            border-radius: 4px;
+            text-align: center;
+            border: 1px solid;
+
+            
+        }
+        
+        .isAllowRetry{
+            color: #fff;
+            background-color: #64ae16;
+            border: none;
+        }
+
+        .isWrongPra{
+            margin-top: 10px;
+        }
+    }
+}

+ 97 - 55
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/paper-test.css

@@ -1,13 +1,14 @@
 .lesson-test-pop {
   position: fixed;
   width: 100%;
-  height: 100%;
+  /* height: 100%; */
   overflow-y: scroll;
   overflow-x: hidden;
   background-color: #f9f9f9;
   z-index: 10;
   top: 0px;
   left: 0px;
+  font-size: 18px;
 }
 .que-box {
     margin-top:10px;
@@ -29,6 +30,15 @@
     padding-top: 3px;
     height: 30px;
 }
+.has-right-ans{
+    background-color: #4fd5a3;
+}
+.has-wrong-ans{
+    background-color: #ff5508;
+}
+.has-no-ans{
+    background-color: #b7b7b7;
+}
 .has-ans {
     border: 1px solid rgba(117, 117, 117, 0.726);
     margin-left: 5px;
@@ -44,7 +54,7 @@
 }
 .ans-box :hover {
     color: #24b880;
-    font-size: 16px;
+    /* font-size: 16px; */
     padding: 2px 5px;
 }
 .has-ans :hover {
@@ -74,18 +84,22 @@
 
 .lesson-test-pop .warmMessage {
     z-index: 999;
+    font-size: 14px;
+}
+.lesson-test-pop .warmMessage h3{
+  font-size: 16px;
+}
+.lesson-test-pop .testTitle .ques-filter {
+    position: absolute;
+    right: 10%;
+    top: 3px;
 }
-    .lesson-test-pop .testTitle .ques-filter {
-        position: absolute;
-        right: 10%;
-        top: 3px;
-    }
 
 .lesson-test-pop .testTitle .ques-filter .filter-text {
   padding: 2px 7px;
   border-radius: 4px;
   color: #515a6e;
-  font-size: 14px;
+  /* font-size: 14px; */
   font-weight: bolder;
   background-color: rgba(0, 0, 0, 0.1);
 }
@@ -161,10 +175,10 @@
   position: relative;
   display: block;
   overflow: auto;
-  height: 95.5vh;
+  height: 96vh;
   background-color: #ffffff;
   left: 0px;
-  font-size: 20px;
+  /* font-size: 20px; */
 }
 
 .lesson-test-pop .questionContent {
@@ -177,34 +191,34 @@
   text-align: center;
   max-width: 100px;
   margin-bottom: 5px;
-  /*margin-top:20px;*/
+  /*margin-top: 20px;*/
 }
 .lesson-test-pop .questioDes {
-    margin-top:20px;
+    margin-top: 20px;
     font-weight: 900;
-    font-size: 20px;
-    /* height:500px; */
-    overflow-y:scroll;
-    /*border:2px solid red;*/
+    /* font-size: 20px; */
+    /* height: 500px; */
+    overflow-y: scroll;
+    /* border: 2px solid red; */
 }
 .lesson-test-pop .que-item {
-    display:flex;
+    display: flex;
     width: 100%;
     /* max-height: 450px; */
     /* overflow-y: scroll; */
-    /*border:1px solid blue;*/
+    /* border: 1px solid blue; */
 }
 
 .lesson-test-pop .que-items {
     width: 100%;
-    /*border:1px solid lightblue;*/
+    /* border: 1px solid lightblue; */
     /* max-height: 200px; */
-    margin-left:10px;
+    margin-left: 10px;
     /*max-height: 200px;*/
-    overflow-y: scroll;
+    /* overflow-y: scroll; */
 }
 .lesson-test-pop .questionNo {
-    margin-bottom:5px;
+    margin-bottom: 5px;
     font-weight: 900;
 }
 .lesson-test-pop .answers{
@@ -247,7 +261,7 @@
 }
 
 .compose-content {
-    /*margin-top: 30px;*/
+    /* margin-top: 30px; */
     width: 100%;
     /* height: 200px; */
     z-index: 0;
@@ -324,11 +338,12 @@
   /* float: left;
   right: -10px; */
   margin-top: 20px;
-  margin-bottom: 100px;
+  /* margin-bottom: 100px; */
   right: 10px;
   font-weight: 900;
   display: flex;
-  flex-wrap:wrap;
+  flex-wrap: wrap;
+  font-size: 14px;
 }
 .lesson-test-pop .pageCtl2 button {
   text-align: center;
@@ -357,7 +372,7 @@
 .lesson-test-pop .analysis{
   margin-top: 20px;
   z-index: 2;
-  font-size: 20px;
+  /* font-size: 20px; */
   transition: opacity 0.2s ease-in;
   opacity: 0;
 }
@@ -458,13 +473,13 @@
   border-collapse: collapse;
   font-weight: 500;
   cursor: pointer;
-  font-size: 14px;
+  /* font-size: 14px; */
   padding: 2px 10px;
   height: 30px;
 }
 .lesson-test-pop .ansSheet .ansSheetQno:hover {
   color: #24b880;
-  font-size: 16px;
+  /* font-size: 16px; */
   padding: 2px 10px;
   background-color: #ececec;
 }
@@ -513,6 +528,9 @@
   }
 }
 @media screen and (max-width: 1366px) {
+    /* .lesson-test-pop{
+      font-size: 18px;
+    } */
     .lesson-test-pop .testTitle .ques-filter {
         right: 15%;
     }
@@ -543,8 +561,8 @@
         margin-top: 50px;
     }
     .compose-box {
-        background-color: #24b880;
-        color: white;
+        /* background-color: #24b880;
+        color: white; */
         width: 95%;
         border-radius: 6px;
     }
@@ -557,7 +575,7 @@
     .compose-content {
         margin-top: 30px;
         width: 95%;
-        height: 200px;
+        /* height: 200px; */
         margin-bottom:30px;
         z-index: 0;
     }
@@ -578,10 +596,13 @@
         position: relative;
         display: block;
         overflow: auto;
-        height: 95vh;
+        height: 97vh;
         background-color: #ffffff;
         left: 0px;
     }
+    .lesson-test-pop .que-box{
+        max-height: 760px;
+    }
     .lesson-test-pop .pageCtl2 {
         position: relative;
         /* float: right;
@@ -595,6 +616,20 @@
         margin: 0 10px 10px 10px;
     }
 }
+@media screen and (max-width: 1024px) {
+    .lesson-test-pop{
+        font-size: 14px;
+    }
+    .lesson-test-pop .ans-box{
+        font-size: 13px;
+    }
+    .lesson-test-pop .pageCtl2{
+      font-size: 12px;
+    }
+    .lesson-test-pop .que-box{
+      max-height: 450px;
+    }
+}
 @media screen and (max-width: 991px) {
     .lesson-test-pop .testTitle .ques-filter {
         right: 25%;
@@ -616,35 +651,48 @@
         left: 65%;
     }
 
-    .lesson-test-pop .questionArea {
+    /* .lesson-test-pop .questionArea {
         height: auto;
-    }
+    } */
 
-    .lesson-test-pop .ansArea {
+    /* .lesson-test-pop .ansArea {
         position: relative;
-    }
+    } */
 }
-@media screen and (max-width: 767px) {
+@media screen and (max-width: 768px) {
+    .lesson-test-pop{
+      font-size: 14px;
+    }
     .lesson-test-pop .testTitle .ques-filter {
         left: 38%;
     }
-}
-@media screen and (max-width: 767px) {
     .lesson-test-pop .ansSheet {
-        font-size: 10px;
-        width: 80%;
+      /* font-size: 10px; */
+      width: 80%;
     }
-}
-@media screen and (max-width: 767px) {
     .lesson-test-pop .questionDesImg {
-        width: 40%;
-        margin-top: 20px;
+      width: 40%;
+      margin-top: 20px;
     }
-}
-@media screen and (max-width: 767px) {
     .lesson-test-pop .myProgressBar {
-        right: 30%;
+      right: 30%;
+    }
+    .lesson-test-pop .questionArea {
+      /* font-size: 18px; */
     }
+    .lesson-test-pop .questioDes {
+        /* overflow-y: scroll; */
+        /* font-size: 18px; */
+    }
+}
+@media screen and (max-width: 767px) {
+    
+}
+@media screen and (max-width: 767px) {
+    
+}
+@media screen and (max-width: 767px) {
+    
 }
 @media screen and (max-width: 680px) {
     .lesson-test-pop .myProgressBar {
@@ -652,11 +700,5 @@
     }
 }
 @media screen and (max-width: 767px) {
-    .lesson-test-pop .questionArea {
-        font-size: 18px;
-    }
-    .lesson-test-pop .questioDes {
-        /* overflow-y: scroll; */
-        font-size: 18px;
-    }
+    
 }

+ 5 - 5
TEAMModelOS/ClientApp/src/common/BaseAreaPicker.vue

@@ -38,12 +38,12 @@
 </script>
 <style>
 	.distpicker-address-wrapper select {
-		background-color: #575757;
-		color: #cacaca;
+		background-color: #575757 !important;
+		color: #cacaca !important;
 		margin: 5px 0;
-		font-size: 14px;
-		height: 35px;
-		border: 0;
+		font-size: 14px !important;
+		height: 35px !important;
+		border: 0 !important;
 		display: inline-block;
 		position: relative;
 		outline: none;

+ 5 - 31
TEAMModelOS/ClientApp/src/common/BaseLayout.less

@@ -38,7 +38,7 @@
         top: 70px;
         bottom: 0px;
         width: 100%;
-        padding-left: 191px;
+        padding-left: 192px;
         overflow-y: auto;
         background: var(--body-bg);
         transition: padding-left 0.4s;
@@ -128,14 +128,14 @@
     width: 100%;
     text-align: right;
     cursor: pointer;
-    transition: background 1s;
+    transition: background 0.5s;
     padding-right: 5px;
-    padding-top: 5px;
-    padding-bottom: 5px;
+    padding-top: 1px;
+    padding-bottom: 1px;
     background:var(--side-bg);
     &:hover {
         background: #404040;
-        transition: background 1s;
+        transition: background 0.5s;
     }
 
     &:hover .collapse-icon {
@@ -148,33 +148,7 @@
     transform: translateX(-18px);
     transition:transform 0.2s;
 }
-.sub-item-wrap {
-    position: relative;
-}
-
-.sub-item-wrap::before {
-    content: '';
-    z-index: -1;
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    pointer-events: none;
-    background-image: linear-gradient(270deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
-    transform-origin: center right;
-    transform: scaleX(0);
-}
 
-.sub-item-wrap-active {
-    z-index: 1;
-}
-
-.sub-item-wrap-active::before {
-    transform-origin: center left;
-    transform: scaleX(1);
-    transition: transform 0.3s ease-in-out;
-}
 .menu-item-text {
     display: inline-block;
     overflow: hidden;

+ 73 - 23
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -31,11 +31,11 @@
                                         <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
                                         <span>{{item.name}}</span>
                                     </template>
-                                    <MenuItem class="sub-item-wrap sub-item-wrap-active" :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll">
+                                    <MenuItem :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll">
                                     <Tooltip :content="menuItem.name" placement="right" transfer v-show="isCollapsed">
                                         <Icon class="sub-menu-icon" :custom="menuItem.icon" size="16" />
                                     </Tooltip>
-                                    <Icon v-show="!isCollapsed" class="sub-menu-icon" :custom="menuItem.icon" size="16"/>
+                                    <Icon v-show="!isCollapsed" class="sub-menu-icon" :custom="menuItem.icon" size="16" />
                                     <span>
                                         {{menuItem.name}}
                                         <span style="color: aqua;margin-left: 2px;font-size: 12px;vertical-align: text-top;">
@@ -49,7 +49,13 @@
                                     <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
                                 </Tooltip>
                                 <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
-                                <span>{{item.name}}</span>
+                                <span>
+                                    {{item.name}}
+                                    <span style="color: aqua;margin-left: 2px;font-size: 12px;vertical-align: text-top;">
+                                        {{item.tag}}
+                                    </span>
+                                </span>
+
                                 </MenuItem>
                             </div>
                         </div>
@@ -64,7 +70,7 @@
                                     <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
                                     <span>{{item.name}}</span>
                                 </template>
-                                <MenuItem class="sub-item-wrap sub-item-wrap-active" :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll && menuItem.isShow">
+                                <MenuItem :name="menuItem.menuName" :to="menuItem.router" v-for="(menuItem,i) in item.child" :key="i" v-show="$access.ability(menuItem.role,menuItem.permission).validateAll && menuItem.isShow">
                                 <Tooltip :content="menuItem.name" placement="right" transfer v-show="isCollapsed">
                                     <Icon class="sub-menu-icon" :custom="menuItem.icon" size="18" />
                                 </Tooltip>
@@ -82,11 +88,15 @@
                                 <Icon :custom="item.icon" style="width:55px;text-align:left;" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
                             </Tooltip>
                             <Icon v-show="!isCollapsed" :custom="item.icon" :class="isCollapsed ? 'collapse-icon-size':''" size="16" />
-                            <span>{{item.name}}</span>
+                            <span>
+                                {{item.name}}
+                                <span style="color: aqua;margin-left: 2px;font-size: 12px;margin-top:3px">
+                                    {{item.tag}}
+                                </span>
+                            </span>
                             </MenuItem>
                         </div>
                     </MenuGroup>
-
                 </vuescroll>
             </Menu>
             <p class="copyright-info" v-show="!isCollapsed">
@@ -461,7 +471,7 @@ export default {
                     icon: 'iconfont icon-task',
                     name: this.$t('system.menu.taskList'),
                     router: '/home/taskList',
-                    tag: '',
+                    tag: '预览',
                     role: 'teacher',
                     permission: '',
                     child: [],
@@ -488,7 +498,7 @@ export default {
             if (cloudSetting.menuStatus == 'close') {
                 this.isCollapsed = true
             }
-			this.isShowLogo = cloudSetting.logoStatus === 'open'
+            this.isShowLogo = cloudSetting.logoStatus === 'open'
         }
     },
     mounted() {
@@ -549,7 +559,30 @@ export default {
     font-size: 12px;
     line-height: 30px;
     height: 30px;
+    position: relative;
+    color: white;
+}
+.ivu-menu-item-group{
+    position: relative;
+}
+.biz-menu .ivu-menu-vertical .ivu-menu-item-group::after {
+    content: "";
+    width: 100%;
+    height: 1px;
+    background: #303030;
+    position: absolute;
+    right: 0px;
+    bottom: -10px;
+    box-shadow:0px 12px 8px -12px #000;
+}
+.biz-menu  .ivu-menu-item-group:nth-child(2)::after {
+    background: transparent;
 }
+.biz-menu  .ivu-menu-item-group:nth-child(2) {
+    margin-top: 30px;
+}
+
+
 .biz-menu .ivu-menu-item-group:first-child {
     margin-top: 0px;
 }
@@ -561,7 +594,8 @@ export default {
 }
 
 .biz-menu .ivu-menu-light {
-    background: var(--side-bg);
+    // background: var(--side-bg);
+    background: #1d1e23;
     color: var(--primary-textColor);
 }
 
@@ -572,7 +606,8 @@ export default {
 .biz-menu
     .ivu-menu-light.ivu-menu-vertical
     .ivu-menu-item-active:not(.ivu-menu-submenu) {
-    background: #101117;
+    background: #33343a;
+    color: white;
     z-index: 2;
 }
 
@@ -585,8 +620,8 @@ export default {
 .menu-item span {
     display: inline-block;
     white-space: nowrap;
-    font-size: 16px;
-    position: absolute;
+    font-size: 15px;
+    // position: absolute;
     width: ~"calc(100% - 50px)";
     max-width: 150px;
     vertical-align: top;
@@ -596,22 +631,25 @@ export default {
 }
 
 .menu-item i {
+    margin-right: 10px;
     transform: translateX(0px);
     transition: font-size 0.5s ease, transform 0.5s ease;
-    vertical-align: sub;
     font-size: 16px;
-    /*color: var(--primary-text-color);*/
 }
 
 .menu-item .ivu-menu .ivu-menu-item {
     color: #cccccc;
 }
 .menu-item .ivu-menu-item {
-    color: hsla(0,0%,100%,.7);
+    color: hsla(0, 0%, 100%, 0.7);
+    display: flex;
+    align-items: center;
 }
 
 .menu-item .ivu-menu-submenu-title {
-    color: hsla(0,0%,100%,.7);
+    color: hsla(0, 0%, 100%, 0.7);
+    display: flex;
+    align-items: center;
 }
 
 .collapsed-menu i {
@@ -623,10 +661,8 @@ export default {
 
 .biz-menu .ivu-icon-ios-arrow-down:before {
     position: absolute;
-    top: -5px;
-    font-size: 12px;
-    opacity: 0.8;
-    color: hsla(0,0%,100%,.7);
+    top: -6px;
+    font-size: 15px;
 }
 
 .collapsed-menu .ivu-icon-ios-arrow-down:before {
@@ -661,25 +697,39 @@ export default {
 
 .biz-menu .ivu-menu-vertical .ivu-menu-item,
 .biz-menu .ivu-menu-vertical .ivu-menu-submenu-title {
-    padding: 10px 24px;
+    padding: 13px 24px;
+}
+.biz-menu .ivu-menu-submenu .ivu-menu-item {
+    background: #101117;
+    display: flex;
+    align-items: center;
 }
 
 .biz-menu
     .ivu-menu-light.ivu-menu-vertical
     .ivu-menu-item-active:not(.ivu-menu-submenu) {
-    color: #1cc0f3;
+    color: #ffffff;
 }
 
 .biz-menu
     .ivu-menu-light.ivu-menu-vertical
     .ivu-menu-item-active:not(.ivu-menu-submenu):after {
+    // background: transparent;
     background: #1cc0f3;
+    width: 1px;
 }
 
 // .ivu-menu-submenu-title:hover .ivu-menu-submenu-title-icon::before,.ivu-menu-submenu-title:hover span, .ivu-menu-submenu-title:hover .ivu-icon{
 //     color: #fff;
 // }
-.ivu-menu-submenu-title:hover .ivu-menu-submenu-title-icon::before{
+.ivu-menu-submenu-title:hover .ivu-menu-submenu-title-icon::before {
     color: rgb(45, 183, 245);
 }
+.ivu-menu-item:hover,
+.ivu-menu-submenu-title:hover {
+    color: white !important;
+    .ivu-icon-ios-arrow-down:before {
+        color: white !important;
+    }
+}
 </style>

+ 10 - 1
TEAMModelOS/ClientApp/src/common/BaseNotification.vue

@@ -1,7 +1,9 @@
 <template>
 	<div class="base-notification">
 		<Poptip :title="$t('utils.newNotice')" class="dark-iview-poptip">
-			<Icon type="md-notifications" />
+			<Badge :count="3">
+				<Icon type="md-notifications" />
+			</Badge>
 			<!-- <div slot="content" class="notice-wrap">
 				<div class="notice-item">
 					<p class="item-name">青城山学校</p>
@@ -37,6 +39,13 @@
 		.dark-iview-poptip .ivu-poptip-popper{
 			padding: 0;
 			top: 40px !important;
+			z-index: 9999;
+		}
+		
+		.ivu-badge-count{
+			height: auto;
+			padding: 2px 3px;
+			line-height: 10px;
 		}
 		
 		.notice-wrap{

+ 0 - 1
TEAMModelOS/ClientApp/src/common/BaseSelectSchool.vue

@@ -42,7 +42,6 @@
 			this.defaultLogo = require('@/assets/icon/default_school.png')
 			// 获取本地存储中的 用户信息
 			let user = JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"));
-			console.log(user)
 			let schoolProfile = localStorage.school_profile ? JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")) :undefined;
 			this.user.schools = user.schools
 			let joinSchools = user.schools && user.schools.length ?  user.schools.filter(i => i.status === 'join') : null

+ 63 - 8
TEAMModelOS/ClientApp/src/common/UploadModal.vue

@@ -1,18 +1,22 @@
 <template>
-    <Modal v-model="uploadStatus" :ok-text="textLoading ? $t('updModal.uploading') : isComplete ? $t('updModal.complete'):$t('updModal.comfirmUpd')" :cancel-text="$t('updModal.cancelUpd')" :title="$t('teachContent.btnUpload')" class="upload-modal dark-iview-modal" width="800" :mask-closable="false" :closable="false" @on-ok="modalOk" @on-cancel="modalCancel" :loading="modalLoading">
+    <Modal v-model="uploadStatus" :ok-text="textLoading ? $t('updModal.uploading') : isComplete ? $t('updModal.complete'):$t('updModal.comfirmUpd')" :cancel-text="$t('updModal.cancelUpd')" :title="$t('teachContent.btnUpload')" class="upload-modal dark-iview-modal" width="900" :mask-closable="false" :closable="false" @on-ok="modalOk" @on-cancel="modalCancel" :loading="modalLoading">
         <div class="upload-file-box">
-            <!-- <p>上传到:{{pdInfo.filterPeriodName}}</p> -->
-            <ResBelong v-show="routerScope == 'school'" showLabel class="upd-to-pd" :pdId="pdId"></ResBelong>
+            <ResBelong @tag-change="getResTags" v-show="routerScope == 'school'" showLabel class="upd-to-pd" :pdId="pdId"></ResBelong>
             <Upload type="drag" action="" :show-upload-list="false" multiple :before-upload="customUpload" class="upload-wrap" :disabled="textLoading">
                 <Icon class="upload-icon" custom="iconfont icon-upload" v-show="!uploadedList.length" />
                 <p class="upload-text" :style="{marginTop: uploadedList.length ? '25px':'0px'}">
                     <Icon size="24" style="font-size: 22px;vertical-align: baseline;margin-right: 5px;" custom="iconfont icon-upload" v-show="uploadedList.length" />
                     {{$t('teachContent.uploadText')}}
                 </p>
-                <p class="upload-text" style="font-size:12px;">{{$t('updModal.tips1')}}</p>
-                <p class="upload-text" :style="{fontSize:'12px',marginBottom: uploadedList.length ? '25px':'50px'}">
+                <p class="upload-text" style="font-size:12px;">
+                    {{$t('updModal.tips1')}}
+                </p>
+                <p class="upload-text" style="font-size:12px;">
                     {{$t('updModal.tips3')}}
                 </p>
+                <p class="upload-text" :style="{fontSize:'12px',marginBottom: uploadedList.length ? '25px':'50px'}">
+                    {{$t('updModal.tips2')}}
+                </p>
             </Upload>
             <div class="upload-file-box">
                 <div class="upload-file-item" v-for="(item,index) in uploadedList" :key="index">
@@ -80,7 +84,12 @@ export default {
             textLoading: false,
             modalLoading: false,
             isComplete: false, //是否完成上传
-            loadingCount: 0
+            loadingCount: 0,
+            tags: {
+                period: '',
+                gradeId: [],
+                subjectId: []
+            }
         }
     },
     props: {
@@ -132,6 +141,13 @@ export default {
         }
     },
     methods: {
+        //资源标签:学段、学科、年级
+        getResTags(data) {
+            console.log(data)
+            this.tags.period = data.period
+            this.tags.subjectId = data.subjects
+            this.tags.gradeId = data.grades
+        },
         //删除文件
         deleteFile(index) {
             this.containerClient.deleteBlob(this.uploadedList[index].blob).then(
@@ -268,6 +284,40 @@ export default {
         modalOk() {
             //已完成上传操作,关闭对话框、emit
             if (this.isComplete) {
+                //保存Blob描述信息
+                //API设计可以优化,如果API参数为对象数据,这里可以避免for循环里面发起请求影响性能
+                if (this.routerScope == 'school') {
+                    this.uploadedList.forEach(item => {
+                        item.periodId = this.tags.period
+                        item.gradeId = this.tags.gradeId.map(item => item + '')
+                        item.subjectId = this.tags.subjectId
+                        let requestData = {
+                            periodId: this.tags.period,
+                            gradeId: this.tags.gradeId.map(item => item + ''),
+                            subjectId: this.tags.subjectId,
+                            scope: 'school',
+                            name: this.$store.state.userInfo.schoolCode,
+                            url: item.blob.substring(1, item.blob.length),
+                            opt: 'add'
+                        }
+                        this.$api.blob.upsertBlobInfo(requestData)
+                    })
+                }
+                //个人资源不用关联学段、学科、年级等信息
+                else {
+                    this.uploadedList.forEach(item => {
+                        let requestData = {
+                            periodId: [],
+                            gradeId: [],
+                            subjectId: [],
+                            scope: 'private',
+                            name: this.$store.state.userInfo.TEAMModelId,
+                            url: item.blob.substring(1, item.blob.length),
+                            opt: 'add'
+                        }
+                        this.$api.blob.upsertBlobInfo(requestData)
+                    })
+                }
                 this.$emit("successData", this.uploadedList)
                 this.uploadedList = []
             } else { //还未上传文件,则上传文件
@@ -362,7 +412,6 @@ export default {
                 this.textLoading = false
                 this.isComplete = true
                 this.modalLoading = false
-
             }
         },
         //处理图片缩略图
@@ -409,12 +458,18 @@ export default {
             }
         }
         // 使用组件接收的值
-        else{
+        else {
             this.routerScope = this.scope
         }
 
     },
     watch: {
+        pdId: {
+            handler(n, o) {
+                this.tags.period = this.pdId
+            },
+            immediate: true
+        },
         urlString: {
             handler(v, o) {
                 if (this.urlString && this.containerName && this.sasString) {

+ 41 - 30
TEAMModelOS/ClientApp/src/components/app-root.vue

@@ -1,43 +1,54 @@
 <template>
     <div id="app" class="container-fluid">
-        <router-view v-if="isRouterAlive"/>
+        <router-view v-if="isRouterAlive" />
     </div>
 </template>
 
 <script>
-    import NavMenu from './nav-menu'
+import NavMenu from './nav-menu'
 
-    export default {
-        components: {
-            'nav-menu': NavMenu,
-        },
-        provide () {    //父组件中通过provide来提供变量,在子组件中通过inject来注入变量。                                             
-            return {
-                reload: this.reload                                              
-            }
-        },
-        methods: {
-            reload() {
-                this.isRouterAlive = false
-                this.$nextTick(function () {
-                    this.isRouterAlive = true
-                })
-            }
-        },
-        data() {
-            return {
-                isRouterAlive:true
-            }
-        },
-        created() {
+export default {
+    components: {
+        'nav-menu': NavMenu,
+    },
+    provide() {    //父组件中通过provide来提供变量,在子组件中通过inject来注入变量。                                             
+        return {
+            reload: this.reload
+        }
+    },
+    methods: {
+        reload() {
+            this.isRouterAlive = false
+            this.$nextTick(function () {
+                this.isRouterAlive = true
+            })
+        }
+    },
+    data() {
+        return {
+            isRouterAlive: true
+        }
+    },
+    created() {
+    },
+    watch: {
+        '$i18n.locale': {
+            handler(n, o) {
+                document.title = this.$t('system.title')
+            },
+            immediate: true
         }
     }
+}
 </script>
 
 <style scoped>
-    #app, body, html {
-        width: 100%;
-        height: 100%;
-        font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI','Microsoft YaHei','微软雅黑', 'Microsoft JhengHei';
-    }
+#app,
+body,
+html {
+    width: 100%;
+    height: 100%;
+    font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI",
+        "Microsoft YaHei", "微软雅黑", "Microsoft JhengHei";
+}
 </style>

+ 1 - 3
TEAMModelOS/ClientApp/src/components/evaluation/ExerciseList.vue

@@ -202,7 +202,6 @@
 			};
 		},
 		created() {
-			console.log('接收到的',this.analysisJson)
 			this.pageSize = this.isAnalysis ? 999 : 5
 			this.pageChange(1)
 		},
@@ -365,7 +364,6 @@
 		},
 		mounted() {
 			this.selectList = this.selQue
-			console.log(this.optionRate)
 		},
 		computed: {
 			curScope() {
@@ -401,7 +399,7 @@
 			optionRate:{
 				handler(n,o){
 					if(n){
-						console.log(n)
+						// console.log(n)
 					}
 				},
 				immediate:true,

文件差異過大導致無法顯示
+ 1 - 1
TEAMModelOS/ClientApp/src/components/public/frontEndMain/Index.vue


+ 2 - 4
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/StudentScore.vue

@@ -94,7 +94,7 @@
                         <span>{{$t("studentWeb.exam.studentScore.comIndex")}}</span>
                     </li>
                 </ul>
-                <ul v-for="(item,index) in scoreInfo.averageMap">
+                <ul v-for="(item, index) in scoreInfo.averageMap" :key="index">
                     <li class="sub-item">
                         <div class="sub-show"><span>{{item.name}}</span></div>
                     </li>
@@ -214,7 +214,6 @@
     </div>
 </template>
 <script>
-
     export default {
         props: {
             stuData: {
@@ -389,7 +388,6 @@
         },
         mounted() {
             this.getPaperData()
-
         },
         watch: {
             stuData() {
@@ -397,7 +395,7 @@
                     this.stuScore = []
                     this.getPaperData()
                 }
-                deep:true
+                deep: true
             }
         }
     }

文件差異過大導致無法顯示
+ 152 - 52
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperTest.vue


+ 1 - 1
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperView.vue

@@ -43,7 +43,7 @@
                     </div>
                 </TabPane>
                 <!-- 成绩分析 -->
-                <TabPane :label="$t('studentWeb.exam.gradeReport')" v-if="isTestOver" name="analyse">
+                <TabPane :label="$t('studentWeb.exam.gradeReport')" v-if="isTestOver && $store.getters.getItemTitle.owner == 'school'" name="analyse">
                     <div class="title-rect-group">
                         <!-- <div class="title-rect" /> -->
                         <h2 class="title-rect-name">{{$t("studentWeb.exam.gradeAnalyse")}}</h2>

+ 70 - 7
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue

@@ -81,7 +81,70 @@
                     <br />
                     {{ $t("studentWeb.empty") }}
                 </div>
-                <div :id="`event${item.id}`"
+                <div v-if="isListNoItem == false">
+                    <div :id="`event${item.id}`"
+                         class="list-new"
+                         @click="sentSelectedEventTitle(item)"
+                         :class="{ 'list-item-selected': selectedCondition(item) }"
+                         v-for="(item, index) in eventShow"
+                         :key="index"
+                    >
+                        <div class="list-new-icon">
+                            <svg-icon v-if="item.eventType == 'HomeWork'" icon-class="doc" />
+                            <svg-icon v-if="item.eventType == 'Preview'"  icon-class="selflearninginTime" />
+                            <svg-icon v-if="item.eventType == 'Exam'" icon-class="multiTest" />
+                            <svg-icon v-if="item.eventType == 'Vote'" icon-class="vote" />
+                            <svg-icon v-if="item.eventType == 'Survey'" icon-class="quesnaire" />
+                        </div>
+                        <div v-if="item.eventType == 'Exam'" class="list-new-test">
+                            <p class="list-item-title">
+                                <span class="list-item-typeMark">{{item.owner == 'school' ? $t('studentWeb.public.schoolExam'):$t('studentWeb.public.privateExam')}}</span>
+                                <span>{{ item.name }}</span>
+                            </p>
+                            <!-- 暂时不改 -->
+                            <!-- <p class="list-item-time isScore" v-show="timeStatus(item) == 'finish'">
+                                得分率:20%
+                            </p> -->
+                            <p class="list-item-time">
+                                {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
+                            </p>
+                        </div>
+                        <div v-if="item.eventType == 'Vote'" class="list-new-test">
+                            <p class="list-item-title">
+                                <span class="list-item-typeMark">{{item.owner == 'school' ? $t('studentWeb.public.schoolVote'):$t('studentWeb.public.privateVote')}}</span>
+                                <span>{{ item.name }}</span>
+                            </p>
+                            <p class="list-item-time">
+                                {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
+                            </p>
+                        </div>
+                        <div v-if="item.eventType == 'Survey'" class="list-new-test">
+                            <p class="list-item-title">
+                                <span class="list-item-typeMark">{{item.owner == 'school' ? $t('studentWeb.public.schoolSurvey'):$t('studentWeb.public.privateSurvey')}}</span>
+                                <span>{{ item.name }}</span>
+                            </p>
+                            <p class="list-item-time">
+                                {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
+                            </p>
+                        </div>
+                        <div class="list-new-type">
+                            <div class="list-new-unDone isAllowRetry" v-show="timeStatus(item) == 'going'">
+                                <span>{{$t("studentWeb.public.going")}}</span>
+                            </div>
+                            <div class="list-new-unDone" v-show="timeStatus(item) == 'finish'">
+                                <span class="isOvertime">{{$t("studentWeb.public.finish")}}</span>
+                            </div>
+                            <!-- 暂时不改 -->
+                            <!-- <div class="list-new-unDone isWrongPra" v-show="timeStatus(item) == 'finish' && item.eventType == 'Exam'">
+                                <span class="">{{$t("studentWeb.exam.report.wrongPractice")}}</span>
+                            </div> -->
+                        </div>
+                            
+                    </div>
+                </div>
+
+
+                <!-- <div :id="`event${item.id}`"
                      class="list-item"
                      @click="sentSelectedEventTitle(item)"
                      :class="{ 'list-item-selected': selectedCondition(item) }"
@@ -106,9 +169,9 @@
                             <p class="list-item-time">
                                 {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
                             </p>
-                            <!-- <p class="list-item-time" v-show="timeStatus(item) == 'finish'">
+                            <p class="list-item-time" v-show="timeStatus(item) == 'finish'">
                                 得分率:20%
-                            </p> -->
+                            </p>
                         </li>
                         <li class="list-item-info"
                             v-if="item.eventType == 'Vote'">
@@ -136,11 +199,11 @@
                         <li class="list-item-unDone" v-show="timeStatus(item) == 'finish'">
                             <div class="isOvertime">{{$t("studentWeb.public.finish")}}</div>
                         </li>
-                        <!-- <li class="list-item-unDone" v-show="timeStatus(item) == 'finish' && item.eventType == 'Exam'">
+                        <li class="list-item-unDone" v-show="timeStatus(item) == 'finish' && item.eventType == 'Exam'">
                             <div class="">{{$t("studentWeb.exam.report.wrongPractice")}}</div>
-                        </li> -->
+                        </li>
                     </ul>
-                </div>
+                </div> -->
                 <div class="list-end"></div>
             </div>
         </div>
@@ -299,7 +362,6 @@
                 //選中第一個
                 let currentfilterArray = [];
                 this.eventShow.length = 0
-                console.log(this.eventTypeCheckers);
                 for (let i = 0; i < this.eventList.length; i++) {
                     if (this.eventPageType.includes(this.eventList[i].eventType)) {
                         // 沒有篩選類型+沒有篩選狀態的情況
@@ -555,4 +617,5 @@
 
 <style scoped>
     @import "~@/assets/student-web/component_styles/event-list.css";
+    @import "~@/assets/student-web/component_styles/event-list-new.css";
 </style>

+ 6 - 5
TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseList.vue

@@ -295,13 +295,13 @@ export default {
   name: "CourseList",
   data() {
     return {
-      currentView:'table',
+      currentView: 'table',
       messageOpen: false,
       timetitle:
         localStorage.getItem("lang") == "tw"
           ? ["時間", "一", "二", "三", "四", "五"]
           : ["time", "Mon", "Tue", "Wed", "Thu", "Fri"],
-        courseList: this.$api.studentWeb.courseList
+      courseList: this.$api.studentWeb.courseList //moke数据
     };
   },
   created() {
@@ -310,12 +310,12 @@ export default {
     }
   },
   methods: {
-    changeView(type){
+    changeView(type) {
       this.currentView=type
     },
     sentFirstItemActive() {
-        let tempArr = [];
-        console.log(this.$api.studentWeb.courseList)
+      let tempArr = [];
+      console.log(this.$api.studentWeb.courseList)
       for (let i = 0; i < this.courseList.length; i++) {
         if (this.courseList[i].courseType != "臨時") {
           tempArr.push(this.courseList[i]);
@@ -323,6 +323,7 @@ export default {
       }
       this.sentSelectedEventTitle(tempArr[0]);
     },
+    // 跳转到当前课程
     sentSelectedEventTitle: function (item) {
       this.$router.push("/courseList#" + item.courseID);
       //改變ItemName的狀態 vuex mutations

+ 0 - 96
TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue

@@ -151,63 +151,6 @@
 				this.nodeInfo.title = node.data.title
 			},
 
-
-			onRelatedContent(node, data, e) {
-				e.stopPropagation() // 防止点击事件穿透到父层
-				this.isRelatedContent = true
-				this.currentEditData = data
-			},
-
-			onShowContent(val, data) {
-				console.log(data)
-				this.contentIndex = val
-				this.currentItems = []
-				this.currentResources = []
-				// data.items.length && this.findQuestionById(data.items)
-				data.resources.length && this.findResourceById(data.resources)
-				this.isShowContent = true
-			},
-
-			/**
-			 * 通过id查询内容信息
-			 * */
-			findResourceById(ids) {
-
-				this.$api.learnActivity.FindSyllabusResourceById(ids).then(
-					res => {
-						if (!res.error) {
-							this.currentResources = res.result.data
-						} else {
-							this.$Message.error("API ERROR")
-						}
-					},
-					err => {
-						this.$Message.error("API ERROR")
-
-					}
-				)
-
-			},
-			/**
-			 * 通过id查询题目信息
-			 * */
-			findQuestionById(ids) {
-				this.$api.learnActivity.FindQuestionById(ids).then(
-					res => {
-						if (!res.error) {
-							this.currentItems = res.result.data
-						} else {
-							this.$Message.error("API ERROR")
-						}
-					},
-					err => {
-						this.$Message.error("API ERROR")
-
-					}
-				)
-			},
-
-
 			// 提交编辑或者新增
 			onSubmitNode() {
 				if (!this.nodeInfo.title) {
@@ -231,50 +174,11 @@
 					}
 					this.currentParentData.children.push(newChild)
 				}
-
 				this.isEditOrAdd = false
 				this.$parent.hasModify = true
 				this.$Message.success(this.isEditItem ? '编辑成功' : '添加成功')
 			},
 
-
-			/**
-			 * 选择关联题目
-			 * @param val 当前已选题目
-			 */
-			onSelectQuestion(val) {
-				this.questionList = val.questions
-			},
-
-			/**
-			 * 选择关联内容
-			 * @param val 当前已选内容
-			 */
-			onSelectFile(val) {
-				this.fileList = val.files
-				console.log(val)
-			},
-
-			/** 保存内容与题目关联 */
-			onSaveNode() {
-				this.isLoading = true
-				this.currentEditData.items = this.currentEditData.items ? [...new Set(this.currentEditData.items.concat(
-					this.questionList.map(item => item.id)))] : [...new Set(this.questionList.map(item => item.id))]
-				this.currentEditData.resources = this.currentEditData.resources ? [...new Set(this.currentEditData
-					.resources.concat(this.fileList.map(item => item.url)))] : [...new Set(this.fileList.map(item =>
-					item.url))]
-				this.$api.syllabus.SaveOrUpdateAsNodes([this.currentEditData]).then(res => {
-					if (!res.error && res) {
-						this.isRelatedContent = false
-						this.$emit('onTreeUpdate')
-						this.isLoading = false
-						this.$parent.hasModify = true
-					} else {
-						this.$Message.warning('获取数据失败')
-					}
-				})
-			},
-
 		},
 		computed:{
 			isFirstLevel(){

+ 4 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/stuAccount.js

@@ -37,6 +37,9 @@ export default {
   delOk:'删除成功',
   isBottom:'已经到底了',
   edit:'修改',
+  adminClass:'行政班管理',
+  teachClass:'教學班管理',
+  stuMgt:'學生管理',
 
   // AddStudent.vue
   accountInfo: '账号资讯',
@@ -90,6 +93,7 @@ export default {
   idWarning:'警告:Excel 內账号重复!',
   gradeWarning:'警告:年级错误',
   setNoErr:"错误:座位号已在校內重复",
+  downloadText:'(下載名單模板)',
 
   // Authorization.vue
   authTitle: '服务授权管理',

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/system.js

@@ -1,4 +1,5 @@
 export default {
+    title:'TEAM Model Cloud',
     loading:'加载中',
     menu:{
         school:'学校',

+ 3 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/teachContent.js

@@ -52,6 +52,8 @@ export default {
   delBatchTips2:'请先选择需要删除的文件!',
   specialChart:'不能包含特殊字符',
   noData:'暂无数据',
-  uploadTo:'上传至:',
+  applyPd:'适用学段:',
+  applySub:'适用学科:',
+   applyGrade:'适用年级:',
   public:'公共资源'
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/updModal.js

@@ -4,7 +4,7 @@
     comfirmUpd:'确认上传',
     cancelUpd:'取消上传',
     tips1:'* 上传相同名字的文件会自动覆盖',
-    tips2:'* 勾选',
+    tips2:'您可以为资源设置适用学段、学科和年级',
     tips3:'支持PPTX文档转换成HTEX教材',
     fileType1:'教材',
     fileType2:'图片',

+ 16 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/settings.js

@@ -75,4 +75,20 @@ export default {
 	copyModal2: "复制失败",
 	openModal1: "应用列表获取失败",
 	openModal2: "api列表获取失败",
+	applyForm:{
+		name:'学校名称',
+		id:'学校简码',
+		code:'学校代码',
+		address:'学校位置',
+		cellphone:'联系方式',
+		content:'备注信息',
+		place1:'选择学校所在地区',
+		place2:'请输入学校详细地址',
+		place3:'请输入您的手机号,邮箱等联系方式',
+		place4:'可填写您的备注信息',
+		submit:'提交申请',
+		submitSuc:'已成功提交申请!',
+		errTip1:'请选择正确的地区!',
+		errTip2:'请将信息填写完整!'
+	}
 }

+ 4 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/stuAccount.js

@@ -37,6 +37,9 @@ export default {
   delOk:'删除成功',
   isBottom:'已经到底了',
   edit:'修改',
+  adminClass:'行政班管理',
+  teachClass:'教学班管理',
+  stuMgt:'学生管理',
 
   // AddStudent.vue
   accountInfo: '账号资讯',
@@ -90,6 +93,7 @@ export default {
   idWarning:'警告:Excel 內账号重复!',
   gradeWarning:'警告:年级错误',
   setNoErr:"错误:座位号已在校內重复",
+  downloadText:'(下载名单模板)',
 
   // Authorization.vue
   authTitle: '服务授权管理',

+ 3 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/studentWeb.js

@@ -311,7 +311,9 @@ export default {
             exitWrongDe: "系统检测您尚未「结束练习」,如您选择「确定」,",
             exitWrongDes: "则目前作答将不保存,下次需重新练习",
             endPractice: "结束练习提示",
-            endPracticeDe: "您将离开错题练习页面",
+            endPracticeDe: "是否继续练习?",
+            endPracticeBtn1: "继续练习",
+            endPracticeBtn2: "结束练习",
             qNo: '题号:',
             correction: '正解',
             queNo: '题目:',

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/system.js

@@ -1,4 +1,5 @@
 export default {
+    title:'醍摩豆云平台',
     loading:'加载中',
     menu:{
         school:'学校',

+ 3 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/teachContent.js

@@ -52,6 +52,8 @@ export default {
   delBatchTips2:'请先选择需要删除的文件!',
   specialChart:'不能包含特殊字符',
   noData:'暂无数据',
-  uploadTo:'上传至:',
+  applyPd:'适用学段:',
+  applySub:'适用学科:',
+  applyGrade:'适用年级:',
   public:'公共资源'
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/totalAnalysis.js

@@ -38,7 +38,7 @@ export default {
 	condition8: '发布年份',
     // totalIndex.vue
     ti_title1: '基本数据统计',
-    ti_title2: '评测数据统计',
+    ti_title2: '学情分析',
     ti_title3: '学科对比统计',
     ti_title4: '年级优生率统计',
     ti_title5: '评测列表数据',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/updModal.js

@@ -4,7 +4,7 @@
     comfirmUpd:'确认上传',
     cancelUpd:'取消上传',
     tips1:'* 上传相同名字的文件会自动覆盖',
-    tips2:'* 勾选',
+    tips2:'您可以为资源设置适用学段、学科和年级',
     tips3:'支持PPTX文档转换成HTEX教材',
     fileType1:'教材',
     fileType2:'图片',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/evaluation.js

@@ -2,7 +2,7 @@ export default {
 	index: {
 		item: '試題',
 		paper: '試卷',
-		addExercise: '新建題',
+		addExercise: '新建題',
 		openAll: '全部展開',
 		collapseAll: '全部折疊',
 		autoCreate: '智慧組卷',

+ 23 - 7
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/settings.js

@@ -12,10 +12,10 @@ export default {
 	menuTips: '選擇左側Menu在網站載入時的預設顯示模式',
 	menuOpen: '預設展開顯示',
 	menuClose: '預設關閉顯示',
-	logoSetting:'Logo顯示設定',
-	logoTips:'選擇是否隱藏左上角平臺Logo',
-	logoOpen:'預設顯示',
-	logoHide:'預設隱藏',
+	logoSetting: 'Logo顯示設定',
+	logoTips: '選擇是否隱藏左上角平臺Logo',
+	logoOpen: '預設顯示',
+	logoHide: '預設隱藏',
 	defaultSchool: '預設學校',
 	curSchool: '當前學校',
 	courseNum: '課程數',
@@ -24,8 +24,8 @@ export default {
 	requestStatus: '送出加入邀請',
 	goSchool: '前往學校',
 	agreeJoin: '同意加入',
-	cancelAdd:'拒絕加入',
-	undoJoin:'撤銷申請',
+	cancelAdd: '拒絕加入',
+	undoJoin: '撤銷申請',
 	requestJoin: '申請加入',
 	inputSearch: '輸入要檢索的學校名稱',
 	modalTip1: '注意',
@@ -37,7 +37,7 @@ export default {
 	columnTool: '操作',
 	modalTip4: '溫馨提示',
 	modalTip5: '確認加入',
-	modalTip6:'確認取消加入',
+	modalTip6: '確認取消加入',
 	submitSucTips: '提交成功',
 	submitFailTips: '操作失敗',
 	joinSucTips: '加入成功!',
@@ -57,4 +57,20 @@ export default {
 	apiMethod: '請求方法',
 	openKeep: '保存平臺',
 	unedit: '取消編輯',
+	applyForm: {
+		name: '學校名稱',
+		id: '學校簡碼',
+		code: '學校程式碼',
+		address: '學校位置',
+		cellphone: '聯繫方式',
+		content: '備註資訊',
+		place1: '選擇學校所在地區',
+		place2: '請輸入學校詳細地址',
+		place3: '請輸入您的手機號,郵箱等聯繫方式',
+		place4: '可填寫您的備註資訊',
+		submit: '提交申請',
+		submitSuc: '已成功提交申請!',
+		errTip1: '請選擇正確的地區!',
+		errTip2: '請將資訊填寫完整!'
+	}
 }

+ 4 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/stuAccount.js

@@ -37,6 +37,9 @@ export default {
   delOk: '刪除成功',
   isBottom: '已經到底了',
   edit:'修改',
+  adminClass:'行政班管理',
+  teachClass:'教學班管理',
+  stuMgt:'學生管理',
 
   //AddStudent.vue
   accountInfo: '帳號資訊',
@@ -90,6 +93,7 @@ export default {
   idWarning:'警告:Excel 內賬號重複! ',
   gradeWarning:'警告:年級錯誤',
   setNoErr:"錯誤:座位號已在校內重複",
+  downloadText:'(下載名單模板)',
 
   //Authorization.vue
   authTitle: '服務授權管理',

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/system.js

@@ -1,4 +1,5 @@
 export default {
+    title:'醍摩豆雲平台',
     loading: '加載中',
     menu: {
         school: '學校',

+ 3 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/teachContent.js

@@ -52,6 +52,8 @@ export default {
   delBatchTips2: '請先選擇需要刪除的檔案!',
   specialChart: '不能包含特殊字元',
   noData: '暫無資料',
-  uploadTo:'上傳至:',
+  applyPd:'適用學段:',
+  applySub:'適用學科:',
+  applyGrade:'適用年級:',
   public:'公共資源'
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/totalAnalysis.js

@@ -39,7 +39,7 @@ export default {
 
 	// totalIndex.vue
 	ti_title1: '基本資料統計',
-	ti_title2: '評量資料統計',
+	ti_title2: '學情分析',
 	ti_title3: '學科比較統計',
 	ti_title4: '年級優生率統計',
 	ti_title5: '評量清單數據',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/updModal.js

@@ -4,7 +4,7 @@
     comfirmUpd:'確認上傳',
     cancelUpd:'取消上傳',
     tips1:'*上傳相同名字的檔案會自動覆蓋',
-    tips2:'*勾選',
+    tips2:'您可以为资源设置适用学段、学科和年级',
     tips3:'支援PPTX檔案轉換成HTEX教材',
     fileType1:'教材',
     fileType2:'圖片',

+ 992 - 0
TEAMModelOS/ClientApp/src/static/countries.js

@@ -0,0 +1,992 @@
+export default [
+    {
+        "en": "Angola",
+        "cn": "安哥拉",
+        "code": "+244"
+    },
+    {
+        "en": "Afghanistan",
+        "cn": "阿富汗",
+        "code": "+93"
+    },
+    {
+        "en": "Alaska(U.S.A)",
+        "cn": "阿拉斯加",
+        "code": "+1907"
+    },
+    {
+        "en": "Albania",
+        "cn": "阿尔巴尼亚",
+        "code": "+335"
+    },
+    {
+        "en": "Algeria",
+        "cn": "阿尔及利亚",
+        "code": "+213"
+    },
+    {
+        "en": "Andorra",
+        "cn": "安道尔共和国",
+        "code": "+376"
+    },
+    {
+        "en": "Anguilla",
+        "cn": "安圭拉岛",
+        "code": "+1254"
+    },
+    {
+        "en": "Antigua and Barbuda",
+        "cn": "安提瓜和巴布达",
+        "code": "+1268"
+    },
+    {
+        "en": "Argentina",
+        "cn": "阿根廷",
+        "code": "+54"
+    },
+    {
+        "en": "Armenia",
+        "cn": "亚美尼亚",
+        "code": "+374"
+    },
+    {
+        "en": "Aruba",
+        "cn": "阿鲁巴岛",
+        "code": "+297"
+    },
+    {
+        "en": "Ascension",
+        "cn": "阿森松",
+        "code": "+247"
+    },
+    {
+        "en": "Australia",
+        "cn": "澳大利亚",
+        "code": "+61"
+    },
+    {
+        "en": "Austria",
+        "cn": "奥地利",
+        "code": "+43"
+    },
+    {
+        "en": "Azerbaijan",
+        "cn": "阿塞拜疆",
+        "code": "+994"
+    },
+    {
+        "en": "Bahamas",
+        "cn": "巴哈马",
+        "code": "+1242"
+    },
+    {
+        "en": "Bahrain",
+        "cn": "巴林",
+        "code": "+973"
+    },
+    {
+        "en": "Bangladesh",
+        "cn": "孟加拉国",
+        "code": "+880"
+    },
+    {
+        "en": "Barbados",
+        "cn": "巴巴多斯",
+        "code": "+1246"
+    },
+    {
+        "en": "Belarus",
+        "cn": "白俄罗斯",
+        "code": "+375"
+    },
+    {
+        "en": "Belgium",
+        "cn": "比利时",
+        "code": "+32"
+    },
+    {
+        "en": "Belize",
+        "cn": "伯利兹",
+        "code": "+501"
+    },
+    {
+        "en": "Benin",
+        "cn": "贝宁",
+        "code": "+229"
+    },
+    {
+        "en": "Bermuda Is",
+        "cn": "百慕大群岛",
+        "code": "+1441"
+    },
+    {
+        "en": "Bhutan",
+        "cn": "不丹",
+        "code": "+975"
+    },
+    {
+        "en": "Bolivia",
+        "cn": "玻利维亚",
+        "code": "+591"
+    },
+    {
+        "en": "Bosnia And Herzegovina",
+        "cn": "波斯尼亚和黑塞哥维那",
+        "code": "+387"
+    },
+    {
+        "en": "Botswana",
+        "cn": "博茨瓦纳",
+        "code": "+267"
+    },
+    {
+        "en": "Brazil",
+        "cn": "巴西",
+        "code": "+55"
+    },
+    {
+        "en": "Brunei",
+        "cn": "文莱",
+        "code": "+673"
+    },
+    {
+        "en": "Bulgaria",
+        "cn": "保加利亚",
+        "code": "+359"
+    },
+    {
+        "en": "Burkina Faso",
+        "cn": "布基纳法索",
+        "code": "+226"
+    },
+    {
+        "en": "Burma",
+        "cn": "缅甸",
+        "code": "+95"
+    },
+    {
+        "en": "Burundi",
+        "cn": "布隆迪",
+        "code": "+257"
+    },
+    {
+        "en": "Cameroon",
+        "cn": "喀麦隆",
+        "code": "+237"
+    },
+    {
+        "en": "Canada",
+        "cn": "加拿大",
+        "code": "+1"
+    },
+    {
+        "en": "Cape Verde",
+        "cn": "佛得角",
+        "code": "+238"
+    },
+    {
+        "en": "Cayman Is",
+        "cn": "开曼群岛",
+        "code": "+1345"
+    },
+    {
+        "en": "Central African Republic",
+        "cn": "中非共和国",
+        "code": "+236"
+    },
+    {
+        "en": "Chad",
+        "cn": "乍得",
+        "code": "+235"
+    },
+    {
+        "en": "Chile",
+        "cn": "智利",
+        "code": "+56"
+    },
+    {
+        "en": "China",
+        "cn": "中国",
+        "code": "+86"
+    },
+    {
+        "en": "Colombia",
+        "cn": "哥伦比亚",
+        "code": "+57"
+    },
+    {
+        "en": "Congo",
+        "cn": "刚果",
+        "code": "+242"
+    },
+    {
+        "en": "Cook Is",
+        "cn": "库克群岛",
+        "code": "+682"
+    },
+    {
+        "en": "Costa Rica",
+        "cn": "哥斯达黎加",
+        "code": "+506"
+    },
+    {
+        "en": "Cuba",
+        "cn": "古巴",
+        "code": "+53"
+    },
+    {
+        "en": "Cyprus",
+        "cn": "塞浦路斯",
+        "code": "+357"
+    },
+    {
+        "en": "Czech Republic",
+        "cn": "捷克",
+        "code": "+420"
+    },
+    {
+        "en": "Republic of Croatia",
+        "cn": "克罗地亚共和国",
+        "code": "+385"
+    },
+    {
+        "en": "Denmark",
+        "cn": "丹麦",
+        "code": "+45"
+    },
+    {
+        "en": "Djibouti",
+        "cn": "吉布提",
+        "code": "+253"
+    },
+    {
+        "en": "Dominica Rep",
+        "cn": "多米尼加共和国",
+        "code": "+1890"
+    },
+    {
+        "en": "Ecuador",
+        "cn": "厄瓜多尔",
+        "code": "+593"
+    },
+    {
+        "en": "Egypt",
+        "cn": "埃及",
+        "code": "+20"
+    },
+    {
+        "en": "EI Salvador",
+        "cn": "萨尔瓦多",
+        "code": "+503"
+    },
+    {
+        "en": "Estonia",
+        "cn": "爱沙尼亚",
+        "code": "+372"
+    },
+    {
+        "en": "Ethiopia",
+        "cn": "埃塞俄比亚",
+        "code": "+251"
+    },
+    {
+        "en": "Fiji",
+        "cn": "斐济",
+        "code": "+679"
+    },
+    {
+        "en": "Finland",
+        "cn": "芬兰",
+        "code": "+358"
+    },
+    {
+        "en": "France",
+        "cn": "法国",
+        "code": "+33"
+    },
+    {
+        "en": "French Guiana",
+        "cn": "法属圭亚那",
+        "code": "+594"
+    },
+    {
+        "en": "French Polynesia",
+        "cn": "法属玻利尼西亚",
+        "code": "+689"
+    },
+    {
+        "en": "Gabon",
+        "cn": "加蓬",
+        "code": "+241"
+    },
+    {
+        "en": "Gambia",
+        "cn": "冈比亚",
+        "code": "+220"
+    },
+    {
+        "en": "Georgia",
+        "cn": "格鲁吉亚",
+        "code": "+995"
+    },
+    {
+        "en": "Germany",
+        "cn": "德国",
+        "code": "+49"
+    },
+    {
+        "en": "Ghana",
+        "cn": "加纳",
+        "code": "+233"
+    },
+    {
+        "en": "Gibraltar",
+        "cn": "直布罗陀",
+        "code": "+350"
+    },
+    {
+        "en": "Greece",
+        "cn": "希腊",
+        "code": "+30"
+    },
+    {
+        "en": "Grenada",
+        "cn": "格林纳达",
+        "code": "+1809"
+    },
+    {
+        "en": "Guam",
+        "cn": "关岛",
+        "code": "+1671"
+    },
+    {
+        "en": "Guatemala",
+        "cn": "危地马拉",
+        "code": "+502"
+    },
+    {
+        "en": "Guinea",
+        "cn": "几内亚",
+        "code": "+224"
+    },
+    {
+        "en": "Guyana",
+        "cn": "圭亚那",
+        "code": "+592"
+    },
+    {
+        "en": "Haiti",
+        "cn": "海地",
+        "code": "+509"
+    },
+    {
+        "en": "Honduras",
+        "cn": "洪都拉斯",
+        "code": "+504"
+    },
+    {
+        "en": "Hongkong",
+        "cn": "香港特别行政区",
+        "code": "+852"
+    },
+    {
+        "en": "Hungary",
+        "cn": "匈牙利",
+        "code": "+36"
+    },
+    {
+        "en": "Iceland",
+        "cn": "冰岛",
+        "code": "+354"
+    },
+    {
+        "en": "India",
+        "cn": "印度",
+        "code": "+91"
+    },
+    {
+        "en": "Indonesia",
+        "cn": "印度尼西亚",
+        "code": "+62"
+    },
+    {
+        "en": "Iran",
+        "cn": "伊朗",
+        "code": "+98"
+    },
+    {
+        "en": "Iraq",
+        "cn": "伊拉克",
+        "code": "+964"
+    },
+    {
+        "en": "Ireland",
+        "cn": "爱尔兰",
+        "code": "+353"
+    },
+    {
+        "en": "Israel",
+        "cn": "以色列",
+        "code": "+972"
+    },
+    {
+        "en": "Italy",
+        "cn": "意大利",
+        "code": "+39"
+    },
+    {
+        "en": "Ivory Coast",
+        "cn": "科特迪瓦",
+        "code": "+225"
+    },
+    {
+        "en": "Jamaica",
+        "cn": "牙买加",
+        "code": "+1876"
+    },
+    {
+        "en": "Japan",
+        "cn": "日本",
+        "code": "+81"
+    },
+    {
+        "en": "Jordan",
+        "cn": "约旦",
+        "code": "+962"
+    },
+    {
+        "en": "Kampuchea (Cambodia )",
+        "cn": "柬埔寨",
+        "code": "+855"
+    },
+    {
+        "en": "Kazakstan",
+        "cn": "哈萨克斯坦",
+        "code": "+327"
+    },
+    {
+        "en": "Kenya",
+        "cn": "肯尼亚",
+        "code": "+254"
+    },
+    {
+        "en": "Korea",
+        "cn": "韩国",
+        "code": "+82"
+    },
+    {
+        "en": "Kuwait",
+        "cn": "科威特",
+        "code": "+965"
+    },
+    {
+        "en": "Kyrgyzstan",
+        "cn": "吉尔吉斯坦",
+        "code": "+331"
+    },
+    {
+        "en": "Laos",
+        "cn": "老挝",
+        "code": "+856"
+    },
+    {
+        "en": "Latvia",
+        "cn": "拉脱维亚",
+        "code": "+371"
+    },
+    {
+        "en": "Lebanon",
+        "cn": "黎巴嫩",
+        "code": "+961"
+    },
+    {
+        "en": "Lesotho",
+        "cn": "莱索托",
+        "code": "+266"
+    },
+    {
+        "en": "Liberia",
+        "cn": "利比里亚",
+        "code": "+231"
+    },
+    {
+        "en": "Libya",
+        "cn": "利比亚",
+        "code": "+218"
+    },
+    {
+        "en": "Liechtenstein",
+        "cn": "列支敦士登",
+        "code": "+423"
+    },
+    {
+        "en": "Lithuania",
+        "cn": "立陶宛",
+        "code": "+370"
+    },
+    {
+        "en": "Luxembourg",
+        "cn": "卢森堡",
+        "code": "+352"
+    },
+    {
+        "en": "Macao",
+        "cn": "澳门特别行政区",
+        "code": "+853"
+    },
+    {
+        "en": "Madagascar",
+        "cn": "马达加斯加",
+        "code": "+261"
+    },
+    {
+        "en": "Malawi",
+        "cn": "马拉维",
+        "code": "+265"
+    },
+    {
+        "en": "Malaysia",
+        "cn": "马来西亚",
+        "code": "+60"
+    },
+    {
+        "en": "Maldives",
+        "cn": "马尔代夫",
+        "code": "+960"
+    },
+    {
+        "en": "Mali",
+        "cn": "马里",
+        "code": "+223"
+    },
+    {
+        "en": "Malta",
+        "cn": "马耳他",
+        "code": "+356"
+    },
+    {
+        "en": "Mariana Is",
+        "cn": "马里亚那群岛",
+        "code": "+1670"
+    },
+    {
+        "en": "Martinique",
+        "cn": "马提尼克",
+        "code": "+596"
+    },
+    {
+        "en": "Mauritius",
+        "cn": "毛里求斯",
+        "code": "+230"
+    },
+    {
+        "en": "Mexico",
+        "cn": "墨西哥",
+        "code": "+52"
+    },
+    {
+        "en": "Moldova",
+        "cn": "摩尔多瓦",
+        "code": "+373"
+    },
+    {
+        "en": "Monaco",
+        "cn": "摩纳哥",
+        "code": "+377"
+    },
+    {
+        "en": "Mongolia",
+        "cn": "蒙古",
+        "code": "+976"
+    },
+    {
+        "en": "Montserrat Is",
+        "cn": "蒙特塞拉特岛",
+        "code": "+1664"
+    },
+    {
+        "en": "Morocco",
+        "cn": "摩洛哥",
+        "code": "+212"
+    },
+    {
+        "en": "Mozambique",
+        "cn": "莫桑比克",
+        "code": "+258"
+    },
+    {
+        "en": "Namibia",
+        "cn": "纳米比亚",
+        "code": "+264"
+    },
+    {
+        "en": "Nauru",
+        "cn": "瑙鲁",
+        "code": "+674"
+    },
+    {
+        "en": "Nepal",
+        "cn": "尼泊尔",
+        "code": "+977"
+    },
+    {
+        "en": "Netheriands Antilles",
+        "cn": "荷属安的列斯",
+        "code": "+599"
+    },
+    {
+        "en": "Netherlands",
+        "cn": "荷兰",
+        "code": "+31"
+    },
+    {
+        "en": "New Zealand",
+        "cn": "新西兰",
+        "code": "+64"
+    },
+    {
+        "en": "Nicaragua",
+        "cn": "尼加拉瓜",
+        "code": "+505"
+    },
+    {
+        "en": "Niger",
+        "cn": "尼日尔",
+        "code": "+227"
+    },
+    {
+        "en": "Nigeria",
+        "cn": "尼日利亚",
+        "code": "+234"
+    },
+    {
+        "en": "North Korea",
+        "cn": "朝鲜",
+        "code": "+850"
+    },
+    {
+        "en": "Norway",
+        "cn": "挪威",
+        "code": "+47"
+    },
+    {
+        "en": "Oman",
+        "cn": "阿曼",
+        "code": "+968"
+    },
+    {
+        "en": "Pakistan",
+        "cn": "巴基斯坦",
+        "code": "+92"
+    },
+    {
+        "en": "Panama",
+        "cn": "巴拿马",
+        "code": "+507"
+    },
+    {
+        "en": "Papua New Cuinea",
+        "cn": "巴布亚新几内亚",
+        "code": "+675"
+    },
+    {
+        "en": "Paraguay",
+        "cn": "巴拉圭",
+        "code": "+595"
+    },
+    {
+        "en": "Peru",
+        "cn": "秘鲁",
+        "code": "+51"
+    },
+    {
+        "en": "Philippines",
+        "cn": "菲律宾",
+        "code": "+63"
+    },
+    {
+        "en": "Poland",
+        "cn": "波兰",
+        "code": "+48"
+    },
+    {
+        "en": "Portugal",
+        "cn": "葡萄牙",
+        "code": "+351"
+    },
+    {
+        "en": "Puerto Rico",
+        "cn": "波多黎各",
+        "code": "+1787"
+    },
+    {
+        "en": "Qatar",
+        "cn": "卡塔尔",
+        "code": "+974"
+    },
+    {
+        "en": "Reunion",
+        "cn": "留尼旺",
+        "code": "+262"
+    },
+    {
+        "en": "Romania",
+        "cn": "罗马尼亚",
+        "code": "+40"
+    },
+    {
+        "en": "Russia",
+        "cn": "俄罗斯",
+        "code": "+7"
+    },
+    {
+        "en": "Saint Lueia",
+        "cn": "圣卢西亚",
+        "code": "+1758"
+    },
+    {
+        "en": "Saint Vincent",
+        "cn": "圣文森特岛",
+        "code": "+1784"
+    },
+    {
+        "en": "Samoa Eastern",
+        "cn": "东萨摩亚(美)",
+        "code": "+684"
+    },
+    {
+        "en": "Samoa Western",
+        "cn": "西萨摩亚",
+        "code": "+685"
+    },
+    {
+        "en": "San Marino",
+        "cn": "圣马力诺",
+        "code": "+378"
+    },
+    {
+        "en": "Sao Tome and Principe",
+        "cn": "圣多美和普林西比",
+        "code": "+239"
+    },
+    {
+        "en": "Saudi Arabia",
+        "cn": "沙特阿拉伯",
+        "code": "+966"
+    },
+    {
+        "en": "Senegal",
+        "cn": "塞内加尔",
+        "code": "+221"
+    },
+    {
+        "en": "Seychelles",
+        "cn": "塞舌尔",
+        "code": "+248"
+    },
+    {
+        "en": "Sierra Leone",
+        "cn": "塞拉利昂",
+        "code": "+232"
+    },
+    {
+        "en": "Singapore",
+        "cn": "新加坡",
+        "code": "+65"
+    },
+    {
+        "en": "Slovakia",
+        "cn": "斯洛伐克",
+        "code": "+421"
+    },
+    {
+        "en": "Slovenia",
+        "cn": "斯洛文尼亚",
+        "code": "+386"
+    },
+    {
+        "en": "Solomon Is",
+        "cn": "所罗门群岛",
+        "code": "+677"
+    },
+    {
+        "en": "Somali",
+        "cn": "索马里",
+        "code": "+252"
+    },
+    {
+        "en": "South Africa",
+        "cn": "南非",
+        "code": "+27"
+    },
+    {
+        "en": "Spain",
+        "cn": "西班牙",
+        "code": "+34"
+    },
+    {
+        "en": "SriLanka",
+        "cn": "斯里兰卡",
+        "code": "+94"
+    },
+    {
+        "en": "St.Lucia",
+        "cn": "圣卢西亚",
+        "code": "+1758"
+    },
+    {
+        "en": "St.Vincent",
+        "cn": "圣文森特",
+        "code": "+1784"
+    },
+    {
+        "en": "Sudan",
+        "cn": "苏丹",
+        "code": "+249"
+    },
+    {
+        "en": "Suriname",
+        "cn": "苏里南",
+        "code": "+597"
+    },
+    {
+        "en": "Swaziland",
+        "cn": "斯威士兰",
+        "code": "+268"
+    },
+    {
+        "en": "Sweden",
+        "cn": "瑞典",
+        "code": "+46"
+    },
+    {
+        "en": "Switzerland",
+        "cn": "瑞士",
+        "code": "+41"
+    },
+    {
+        "en": "Syria",
+        "cn": "叙利亚",
+        "code": "+963"
+    },
+    {
+        "en": "Taiwan",
+        "cn": "台湾",
+        "code": "+886"
+    },
+    {
+        "en": "Tajikstan",
+        "cn": "塔吉克斯坦",
+        "code": "+992"
+    },
+    {
+        "en": "Tanzania",
+        "cn": "坦桑尼亚",
+        "code": "+255"
+    },
+    {
+        "en": "Thailand",
+        "cn": "泰国",
+        "code": "+66"
+    },
+    {
+        "en": "Togo",
+        "cn": "多哥",
+        "code": "+228"
+    },
+    {
+        "en": "Tonga",
+        "cn": "汤加",
+        "code": "+676"
+    },
+    {
+        "en": "Trinidad and Tobago",
+        "cn": "特立尼达和多巴哥",
+        "code": "+1809"
+    },
+    {
+        "en": "Tunisia",
+        "cn": "突尼斯",
+        "code": "+216"
+    },
+    {
+        "en": "Turkey",
+        "cn": "土耳其",
+        "code": "+90"
+    },
+    {
+        "en": "Turkmenistan",
+        "cn": "土库曼斯坦",
+        "code": "+993"
+    },
+    {
+        "en": "Uganda",
+        "cn": "乌干达",
+        "code": "+256"
+    },
+    {
+        "en": "Ukraine",
+        "cn": "乌克兰",
+        "code": "+380"
+    },
+    {
+        "en": "United Arab Emirates",
+        "cn": "阿拉伯联合酋长国",
+        "code": "+971"
+    },
+    {
+        "en": "United Kiongdom",
+        "cn": "英国",
+        "code": "+44"
+    },
+    {
+        "en": "United States of America",
+        "cn": "美国",
+        "code": "+1"
+    },
+    {
+        "en": "Uruguay",
+        "cn": "乌拉圭",
+        "code": "+598"
+    },
+    {
+        "en": "Uzbekistan",
+        "cn": "乌兹别克斯坦",
+        "code": "+233"
+    },
+    {
+        "en": "Venezuela",
+        "cn": "委内瑞拉",
+        "code": "+58"
+    },
+    {
+        "en": "Vietnam",
+        "cn": "越南",
+        "code": "+84"
+    },
+    {
+        "en": "Yemen",
+        "cn": "也门",
+        "code": "+967"
+    },
+    {
+        "en": "Yugoslavia",
+        "cn": "南斯拉夫",
+        "code": "+381"
+    },
+    {
+        "en": "Zimbabwe",
+        "cn": "津巴布韦",
+        "code": "+263"
+    },
+    {
+        "en": "Zaire",
+        "cn": "扎伊尔",
+        "code": "+243"
+    },
+    {
+        "en": "Zambia",
+        "cn": "赞比亚",
+        "code": "+260"
+    }
+]

+ 1 - 1
TEAMModelOS/ClientApp/src/store/module/serviceDriveAuth.js

@@ -17,7 +17,7 @@ export default {
     spaceStatus: undefined,
     serviceIntroIsOpen: [],
     hiteachListItemIsOpen: [], //存放每個開關
-    currentTab:0,//0 服務清單, 1 hiteach 清單
+    currentTab:1,//0 服務清單, 1 hiteach 清單
 
     //接實際api使用,一開始序號為空
 

+ 1 - 1
TEAMModelOS/ClientApp/src/store/module/studentWeb.js

@@ -17,7 +17,7 @@ export default {
     //定義狀態
     state: {
         lang: "zh-TW", //存放
-        sideBarIsOpen: true, //存放側邊欄是否開合
+        sideBarIsOpen: true, //存放側邊欄
         userInfo: {
             name: '',
             studentId: '',

+ 0 - 19
TEAMModelOS/ClientApp/src/view/Home.vue

@@ -26,9 +26,6 @@ export default {
     name: 'headers',
     props: ['parentToChild', 'identityselect'],
     components: {},
-    computed: {
-
-    },
     data() {
         return {
             isShowMock: false,
@@ -38,17 +35,6 @@ export default {
         }
     },
     created() {
-        //刷新重置vuex
-        console.log('进入大云...')
-        console.log(this.$store)
-
-        //  window.addEventListener('beforeunload',() => {
-        //     if(this.$store.state.user.school_profile.school_base){
-        //         schoolStr = encodeURIComponent(JSON.stringify(this.$store.state.user.school_profile.school_base), "utf-8")
-        //         localStorage.setItem('school_profile', schoolStr)
-        //     }
-        // })
-
         let user = JSON.parse(decodeURIComponent(localStorage.userInfo, "utf-8"))
         let user_profile = JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8"))
         if (user_profile.schools) {
@@ -90,11 +76,6 @@ export default {
         },
         basicMenu(name) {
             if (name == 'quit') {
-                //     localStorage.removeItem('access_token')
-                //     localStorage.removeItem('expires_in')
-                //     localStorage.removeItem('userInfo')
-                //     localStorage.removeItem('userAccess')
-                //     localStorage.removeItem('user_details')
                 this.$store.commit('user/resetSchoolProfile')
                 this.$User.logout()
                 this.$router.push({

+ 51 - 31
TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue

@@ -5,10 +5,12 @@
 			<span class="select-model btn-delete" @click="onDeleteBlock" v-if="!isAutoCreate">删除</span>
 		</div>
 		<p class="margin-block"></p>
-		<!-- <div @mouseenter="isShowTools = true" @mouseleave="isShowTools = false"> -->
 		<div >
 			<div :id="ids" class="sheet-Editor" ></div>
-			<div v-for="(item,index) in fixArr" :id="ids + 'fix' + index" class="sheet-Editor"></div>
+			<div  v-for="(item,index) in fixArr" :key="index" class="sheet-fix-Editor">
+				<div :id="ids + 'fix' + index" class="sheet-Editor"></div>
+				<span :id="ids + 'fix' + index + 'btn'" class="btn-delete-fix" @click="onDeleteFixBlock(ids + 'fix' + index)">删除</span>
+			</div>
 		</div>
 
 		<Modal v-model="isShowSelectModel" title="设置内容格式" width="600px" @on-ok="doSelectModel">
@@ -112,6 +114,13 @@
 				this.$EventBus.$emit('doRefresh')
 				this.$EventBus.$emit('deleteItem',this.type)
 			},
+			
+			/* 删除附加答题区域富文本块 */
+			onDeleteFixBlock(curId){
+				document.getElementById(curId).remove()
+				document.getElementById(curId + 'btn').remove()
+				this.$EventBus.$emit('doRefresh')
+			},
 
 			/* 切换富文本显示模式(简答题、语文作文、英语作文)*/
 			doSelectModel() {
@@ -220,6 +229,7 @@
 						let lastBottomGap = 20;
 						let curEditorY = Y > paperH ? +((Y % paperH).toFixed(4)) : Y;
 						let curEditorH = editorDom.clientHeight;
+						
 						let leftHeight = paperH - curEditorY - lastBottomGap - SVG_BORDER_MB;
 						let fixHeight = curEditorH - leftHeight + 20
 						if ( curEditorY + curEditorH + lastBottomGap + SVG_BORDER_MB > PAPER_H) {
@@ -295,14 +305,14 @@
 					
 					// 如果vuex有保存 之前的文本内容 则渲染 否则按照默认只显示题号
 					let curSetting = this.hasEditorSetting(this.ids)
-					if (curSetting && curSetting.content) {
+					let hasVuexContent = curSetting && curSetting.content
+					if (hasVuexContent) {
 						this.myEditor.txt.append(curSetting.content);
 					}else{
 						this.myEditor.txt.append(addStr + brHtml);
 					}
 					
 					// 如果自定义插入的是作文题 则进行对应题型渲染
-					console.log('插入的主观题',subjectiveItem)
 					if(subjectiveItem.maxWords > 0){
 						this.myEditor.txt.clear()
 						addStr = '<p>' +  itemOrder + "、 作文(" + (subjectiveItem.score + "分)") + '</p>'; 
@@ -338,18 +348,22 @@
 						let isNewPage = this.$store.state.answerSheet.isNewPage;
 						let lastBottomGap = 20;
 						let rectTop = editorDom.getBoundingClientRect().top
-						let Y = rectTop + scrollDis - 90;
+						let Y = scrollDis > 90 ? scrollDis - Math.abs(rectTop)  - 90 : rectTop + scrollDis - 90;
 						let paperH = PAPER_H;
 						let curEditorY = Y > paperH ? +((Y % paperH).toFixed(4)) : Y;
 						let curEditorH = editorDom.clientHeight; // 默认200px
-						console.log(itemOrder, 'rectTop', rectTop);
-						console.log(itemOrder, 'scrollDis', scrollDis);
-						console.log(itemOrder, '当前Y', Y);
 						let leftHeight = paperH - curEditorY - lastBottomGap - SVG_BORDER_MB;
-						console.log(itemOrder, '高度', curEditorH)
-						console.log(itemOrder, 'LEFT高度', leftHeight)
 						let fixHeight = curEditorH - leftHeight + 20
-						console.log(itemOrder, '需要fix的高度', fixHeight)
+						if(itemOrder === 6){
+							console.log(itemOrder, 'rectTop', rectTop);
+							console.log(itemOrder, 'scrollDis', scrollDis);
+							console.log(itemOrder, '距离第一页顶点的Y', Y);
+							console.log(itemOrder, '距离当前页面顶点的Y', curEditorY);
+							console.log(itemOrder, '高度', curEditorH)
+							console.log(itemOrder, 'LEFT高度', leftHeight)
+							console.log(itemOrder, '需要fix的高度', fixHeight)
+						}
+						
 						// 如果 渲染当前富文本的时候 需要渲染的高度超过当前页的剩余高度 则需要进行加页处理
 						if (curEditorY + curEditorH + lastBottomGap + SVG_BORDER_MB > PAPER_H) {
 							// console.log(itemOrder, Y , curEditorY , curEditorH , '超出了')
@@ -362,8 +376,8 @@
 								heightArr.push(leftHeight)
 								// 如果渲染的客观题高度在这个区间 才需要在下一页添加补充作答区域 其余全部按照正常 跨页处理不需要补充作答区域
 								let fixCount = Math.ceil(fixHeight / SVG_BORDER_PROP.height)
-								console.log(itemOrder + "需要处理跨页,数量为" + fixCount);
-								console.log(itemOrder + "剩余渲染高度" + fixHeight);
+								// console.log(itemOrder + "需要处理跨页,数量为" + fixCount);
+								// console.log(itemOrder + "剩余渲染高度" + fixHeight);
 								for(let i = 0;i < fixCount;i++){
 									this.fixArr.push(0)
 										let curFixHeight = fixHeight > SVG_BORDER_PROP.height  ? SVG_BORDER_PROP.height - 30 : fixHeight
@@ -377,8 +391,8 @@
 								this.$nextTick(() => {
 									let splitHtmlArr = this.getSplitHtml(this.pArr,heightArr)
 									splitHtmlArr.forEach((curEditorContent,editorIndex) => {
-										console.log('富文本的分割高度',heightArr)
-										console.log('富文本的分割',splitHtmlArr)
+										// console.log('富文本的分割高度',heightArr)
+										// console.log('富文本的分割',splitHtmlArr)
 										
 										let editorHeight = curEditorContent.html === '' ? heightArr[editorIndex] : heightArr[editorIndex]
 										// let curEditorContent = this.getSplitHtml(this.pArr,curEditorHeight)
@@ -695,6 +709,7 @@
 					document
 						.getElementById(curId)
 						.getElementsByClassName("w-e-toolbar")[0].style.display = "flex";
+					document.getElementById(curId + 'btn').style.display = "inline-flex";
 				};
 				editor.config.onblur = (html) => {
 					let scrollHeight = editor.$textElem.elems[0].scrollHeight
@@ -705,7 +720,8 @@
 						// this.$EventBus.$emit('doRefresh')
 					}
 					document.getElementById(curId) && (document.getElementById(curId).getElementsByClassName(
-						"w-e-toolbar")[0].style.display = "none");
+						"w-e-toolbar")[0].style.display = "none") && (document.getElementById(curId + 'btn').style.display = "none")
+							
 					this.$store.commit('setEditorHeight', {
 						id: curId,
 						height: editor.config.height,
@@ -757,21 +773,6 @@
 						);
 						this.curPropItem = this.type === "0" ? this.completeItems : n;
 						this.doRenderEditor(this.curPropItem);
-						if(this.type !== "0"){
-							// setTimeout(() => {
-							// 	if(n[0].maxWords > 0){
-							// 		console.log('语文作文',n.maxWords)
-							// 		this.wordCount = n[0].maxWords
-							// 		this.curModel = '3'
-							// 		this.doSelectModel()
-							// 	}else if(n[0].maxLines > 0){
-							// 		console.log('英语作文',n.maxLines)
-							// 		this.lineCount = n[0].maxLines
-							// 		this.curModel = '2'
-							// 		this.doSelectModel()
-							// 	}
-							// },3000)
-						}
 					}
 				},
 				immediate: true,
@@ -892,4 +893,23 @@
 		margin: 0 4px;
 		display: inline-block;
 	}
+
+	.sheet-fix-Editor{
+		position: relative;
+	}
+	.sheet-fix-Editor .btn-delete-fix{
+		position: absolute;
+		padding: 3px 10px;
+		border-radius: 4px;
+		right: 100px;
+		top: 10px;
+		font-size: 12px;
+		background-color: orangered;
+		display: none;
+		justify-content: center;
+		align-items: center;
+		color: #fff;
+		z-index: 99;
+		cursor: pointer;
+	}
 </style>

+ 2 - 1
TEAMModelOS/ClientApp/src/view/evaluation/bank/ExerciseList.vue

@@ -556,8 +556,9 @@
 					this.exerciseList = await this.$evTools.getFullItem(simpleList);
 					this.currentPage = page;
 					this.pageScrollTo(0);
+					this.onHandleToggle(true)
 				} catch (e) {
-					console.log(e);
+					this.$Message.error('Blob Error : ' + e)
 				}
 			},
 

+ 3 - 3
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseFilter.vue

@@ -11,21 +11,21 @@
 		<div class="filter-item" v-show="(isShowSchoolBank || (filterOrigin === schoolCode)) &&  hasSchool">
 					<span class="filter-title">{{$t('evaluation.filter.period')}}:</span>
 					<RadioGroup v-model="filterPeriod" type="button" @on-change="filterPeriodChange">
-						<Radio v-for="(item, index) in periodList" :key="index" :label="index">{{ item.name }}<span class="filter-count"></span></Radio>
+						<Radio v-for="(item, index) in periodList" :key="index" :label="index">{{ item.name }}<span class="filter-count">({{ filterCounts.periodCountArr.length ? filterCounts.periodCountArr[index] : 0 }})</span></Radio>
 					</RadioGroup>
 				</div>
 				<div class="filter-item" v-show="(isShowSchoolBank || (filterOrigin === schoolCode)) &&  hasSchool">
 					<span class="filter-title">{{$t('evaluation.filter.grade')}}:</span>
 					<CheckboxGroup v-model="filterGrade" border @on-change="filterGradeChange">
 						<Checkbox lable="all">{{$t('evaluation.filter.all')}}</Checkbox>
-						<Checkbox v-for="(item, index) in gradeList" :key="index" :label="index">{{ item }}<span class="filter-count"></span></Checkbox>
+						<Checkbox v-for="(item, index) in gradeList" :key="index" :label="index">{{ item }}<span class="filter-count">({{ filterCounts.gradeCountArr.length ? filterCounts.gradeCountArr[index] : 0 }})</span></Checkbox>
 					</CheckboxGroup>
 				</div>
 				<div class="filter-item" v-show="(isShowSchoolBank || (filterOrigin === schoolCode)) &&  hasSchool">
 					<span class="filter-title">{{$t('evaluation.filter.subject')}}:</span>
 					<CheckboxGroup v-model="filterSubject" border @on-change="filterSubjectChange">
 						<Checkbox lable="all">{{$t('evaluation.filter.all')}}</Checkbox>
-						<Checkbox v-for="(item, index) in subjectList" :key="index" :label="item.id">{{ item.name }}<span class="filter-count"></span></Checkbox>
+						<Checkbox v-for="(item, index) in subjectList" :key="index" :label="item.id">{{ item.name }}<span class="filter-count">({{ filterCounts.subjectCountArr.length ? filterCounts.subjectCountArr[index] : 0 }})</span></Checkbox>
 					</CheckboxGroup>
 				</div>
 		<div class="filter-item">

+ 5 - 1
TEAMModelOS/ClientApp/src/view/evaluation/index/index.vue

@@ -2,7 +2,7 @@
     <div class="evaluation">
         
         <Loading :top="100" v-show="dataLoading" type="3"></Loading>
-        <vuescroll ref="evScroll" id="evScroll">
+        <vuescroll ref="evScroll" id="evScroll" @handle-scroll="handleScroll">
             <div class="ev-body">
                 <div class="ev-content">
                     <router-view />
@@ -42,6 +42,10 @@
               name: name
             })
       },
+	  // 判断容器滚动距离
+	  handleScroll(vertical, horizontal, nativeEvent) {
+	  	console.log(vertical.scrollTop)
+	  },
 
       
     },

+ 8 - 10
TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue

@@ -101,20 +101,24 @@
             <div slot="right" class="evaluation-detail-wrap">
                 <!--顶部菜单-->
                 <div class="evaluation-detail-bar">
+                    <!-- 评测数据 -->
                     <span :class="curBarIndex == 0 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(0)">
                         {{$t('learnActivity.mgtScEv.tab1')}}
                     </span>
+                    <!-- 评测试卷 -->
                     <span :class="curBarIndex == 1 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(1)">
                         {{$t('learnActivity.mgtScEv.tab2')}}
                     </span>
-
-                    <!-- 阅卷功能0531之前完成不了,暂时隐藏 -->
+                    <!-- 阅卷设置 -->
                     <span :class="curBarIndex == 2 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(2)">
                         {{$t('learnActivity.mgtScEv.markSetting')}}
+                        <span style="color:#1cc0f3">(预览)</span>
                     </span>
-                    <!-- <span :class="curBarIndex == 3 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(3)">
+                    <!-- 阅卷数据 -->
+                    <span v-show="isSetting" :class="curBarIndex == 3 ? 'evalustion-bar-item line-bottom-active line-bottom':'evalustion-bar-item line-bottom'" @click="selectBar(3)">
                         {{$t('learnActivity.mgtScEv.markData')}}
-                    </span> -->
+                        <span style="color:#1cc0f3">(预览)</span>
+                    </span>
 
                     <!--取消一键作答和一键评分功能-->
                     <!--<div style="float:right;" v-if="$access.ability('admin','mock-eva').validateAll" v-show="evaListShow[curEvaIndex] && evaListShow[curEvaIndex].progress == 'going'">
@@ -161,12 +165,6 @@
                 </div>
                 <!-- 阅卷基础设置 -->
                 <div :class="curBarIndex == 2 ? 'animated fadeIn evaluation-base-info':'evaluation-base-info animated fadeOutRight'" v-show="curBarIndex == 2">
-                    <!-- <div class="evaluation-test-paper-header" v-if="evaListShow[curEvaIndex]">
-                        <span>{{$t('learnActivity.mgtScEv.evSubject')}}</span>
-                        <span v-for="(item,index) in evaListShow[curEvaIndex].subjects" :key="index" :class="index == curSubIndex ? 'subject-item subject-item-active':'subject-item'" @click="selectSubject(index)">
-                            {{item.name}}
-                        </span>
-                    </div> -->
                     <MarkSetting ref="markSetting" v-if="evaListShow[curEvaIndex]" :evInfo="evaListShow[curEvaIndex]" v-model="isSetting"></MarkSetting>
                 </div>
                 <!-- 阅卷数据 -->

+ 10 - 56
TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkData.vue

@@ -1,52 +1,6 @@
 <template>
     <div class="mark-data-wrap">
         <vuescroll>
-            <!-- 活动阶段 -->
-            <!-- <div class="setting-block">
-                <p class="block-title">{{$t('learnActivity.mark.stage')}}</p>
-                <div class="setting-content step-content">
-                    <Steps :current="2" class="mark-step">
-                        <Step :title="$t('learnActivity.mark.test')" :content="$t('learnActivity.mark.complete')"></Step>
-                        <Step :title="$t('learnActivity.mark.scan')" :content="`${$t('learnActivity.mark.success')}:560/563 ${$t('learnActivity.mark.fail')}:1 ${$t('learnActivity.mark.miss')}:2`"></Step>
-                        <Step :title="$t('learnActivity.mark.mark')" :content="`${$t('learnActivity.mark.markProg')}:80%(420/563)`"></Step>
-                        <Step :title="$t('learnActivity.mark.data')" content=""></Step>
-                    </Steps>
-                </div>
-            </div> -->
-            <!-- 数据概览 -->
-            <div class="setting-block">
-                <p class="block-title">{{$t('learnActivity.mark.dataView')}}</p>
-                <div class="setting-content count-content">
-                    <div class="count-wrap">
-                        <p class="count-num">100</p>
-                        <p class="count-label">
-                            <Icon custom="iconfont icon-scanning" class="count-icon" size="16" />
-                            {{$t('learnActivity.mark.scanOk')}}
-                        </p>
-                    </div>
-                    <div class="count-wrap">
-                        <p class="count-num">0</p>
-                        <p class="count-label">
-                            <Icon type="md-warning" class="count-icon" size="16" />
-                            {{$t('learnActivity.mark.scanErr')}}
-                        </p>
-                    </div>
-                    <div class="count-wrap">
-                        <p class="count-num">1</p>
-                        <p class="count-label">
-                            <Icon type="ios-bug" class="count-icon" size="16" />
-                            {{$t('learnActivity.mark.errDeclare')}}
-                        </p>
-                    </div>
-                    <div class="count-wrap">
-                        <p class="count-num">2</p>
-                        <p class="count-label">
-                            <Icon custom="iconfont icon-arb" class="count-icon" size="16" />
-                            {{$t('learnActivity.mark.arbDeclare')}}
-                        </p>
-                    </div>
-                </div>
-            </div>
             <!-- 各科概览 -->
             <div class="setting-block">
                 <p class="block-title">{{$t('learnActivity.mark.subData')}}</p>
@@ -134,16 +88,16 @@ export default {
                     key: 'num',
                     align: 'center'
                 },
-                {
-                    title: this.$t('learnActivity.mark.scanProg'),
-                    slot: 'scanPerc',
-                    align: 'center'
-                },
-                {
-                    title: this.$t('learnActivity.mark.assignStatus'),
-                    slot: 'status',
-                    align: 'center'
-                },
+                // {
+                //     title: this.$t('learnActivity.mark.scanProg'),
+                //     slot: 'scanPerc',
+                //     align: 'center'
+                // },
+                // {
+                //     title: this.$t('learnActivity.mark.assignStatus'),
+                //     slot: 'status',
+                //     align: 'center'
+                // },
                 {
                     title: this.$t('learnActivity.mark.errDeclare'),
                     slot: 'err',

+ 8 - 0
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.less

@@ -340,4 +340,12 @@
     color: #ff9900;
     text-align: center;
     margin-top: 80px;
+}
+.qr-code-text{
+    display: block;
+    margin: auto;
+    text-align: center;
+    margin-top: 8px;
+    margin-bottom: -14px;
+    color: black;
 }

+ 3 - 1
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue

@@ -318,7 +318,9 @@
             <StudentList @getSelectInfo="(selction)=>{selections = selction}"></StudentList>
         </Modal>
         <div class="qr-code-wrap" v-show="showQrStatus" @click="showQrStatus = false">
-            <div id="qrcode" :class="showQrStatus ? 'animated fadeIn':'animated fadeOut'" ref="qrcode" style="padding:20px;background-color:white;width:320px;margin:auto;"></div>
+            <div id="qrcode" :class="showQrStatus ? 'animated fadeIn':'animated fadeOut'" ref="qrcode" style="padding:20px;background-color:white;width:320px;margin:auto;">
+                <span class="qr-code-text">扫码加入名单</span>
+            </div>
         </div>
     </div>
 </template>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/questionnaire/ManageQuestionnaire.less

@@ -181,7 +181,7 @@
 
     .qn-info-box {
         border-right: 1px solid @borderColor;
-		background-color: #2b2b2e;
+		background-color: #242328;
 
         .qn-info-wrap{
             color:#AAAAAA !important;

+ 2 - 2
TEAMModelOS/ClientApp/src/view/schoolmgmt/ClassroomSetting/ClassroomSetting.less

@@ -199,14 +199,14 @@
 .class-list {
     width: 100%;
     height:~"calc(100% - 90px)";
-    padding-left: 15px;
+    padding-left: 8px;
     
 }
 .active-item-bg {
     background-image: linear-gradient(90deg, rgba(30,30,30,0) 0%, rgba(110,110,110,.2) 50%, rgba(110,110,110,.4) 100%);
 }
 .class-list-item {
-    padding: 8px 0px;
+    padding: 8px 0px 8px 10px;
     .border(bottom);
     cursor:pointer;
     position:relative;

+ 4 - 4
TEAMModelOS/ClientApp/src/view/schoolmgmt/ClassroomSetting/ClassroomSetting.vue

@@ -81,10 +81,10 @@
                     <!-- <span :class="currentTabIndex == 1 ? 'main-header-tab line-bottom line-bottom-active':'main-header-tab line-bottom'" @click="selectTab(1)">
                         {{$t('schoolBaseInfo.tab3')}}
                     </span> -->
-                    <!-- hiteach关联 -->
-                    <span :class="currentTabIndex == 3 ? 'main-header-tab line-bottom line-bottom-active':'main-header-tab line-bottom'" @click="selectTab(3)">
+                    <!-- hiteach关联 暂时去掉-->
+                    <!-- <span :class="currentTabIndex == 3 ? 'main-header-tab line-bottom line-bottom-active':'main-header-tab line-bottom'" @click="selectTab(3)">
                         {{$t('schoolBaseInfo.tab4')}}
-                    </span>
+                    </span> -->
                     <!-- 课表 -->
                     <span :class="currentTabIndex == 4 ? 'main-header-tab line-bottom line-bottom-active':'main-header-tab line-bottom'" @click="selectTab(4)">
                         {{$t('schoolBaseInfo.cusTabel')}}
@@ -287,7 +287,7 @@ export default {
             editStatus: true,//可切换编辑状态
             noStatus: false,
             isSearch: false,
-            currentTabIndex: 3,
+            currentTabIndex: 4,
             isListLoading: false,
             isSaveLoading: false,
             hiteachListLoading: true,

+ 335 - 395
TEAMModelOS/ClientApp/src/view/serviceDriveAuth/SubComponents/HiteachAuthList.vue

@@ -1,242 +1,182 @@
 <template>
-  <div class="hiteachAuth-list">
-    <!-- 新增知识点弹窗 -->
-    <Modal
-      id="hiteachAuth-modal"
-      ref="pointRef"
-      v-model="isOpenRemove"
-      :title="title"
-      
-    >
-      <p>{{$t("serviceDriveAuth['當前您所選中的PC']")}}【{{ currentConfirmRemovePC }}】{{$t("serviceDriveAuth[',確定解除授權?']")}}</p>
-      <p>{{$t("serviceDriveAuth['解除授權後,可在教室中的電腦再次進行綁定授權。']")}}</p>
+    <div class="hiteachAuth-list">
+        <!-- 新增知识点弹窗 -->
+        <Modal id="hiteachAuth-modal" ref="pointRef" v-model="isOpenRemove" :title="title">
+            <p>{{$t("serviceDriveAuth['當前您所選中的PC']")}}【{{ currentConfirmRemovePC }}】{{$t("serviceDriveAuth[',確定解除授權?']")}}</p>
+            <p>{{$t("serviceDriveAuth['解除授權後,可在教室中的電腦再次進行綁定授權。']")}}</p>
 
-      <div slot="footer">
-        <Button type="text" @click="isOpenRemove = false">{{$t("serviceDriveAuth['取消']")}}</Button>
-        <Button type="primary" @click="removeUserPC(currentConfirmRemovePC)"
-          >{{$t("serviceDriveAuth['確定']")}}</Button
-        >
-      </div>
-    </Modal>
-    <Loading v-if="isloading == true"></Loading>
-    <div class="service-list">
-      <div class="service-listTitle"><span class="title-item" @click="setTab(0)">{{$t("serviceDriveAuth['服務授權列表']")}}</span> <span class="title-item" @click="setTab(1)" :class="{ 'title-checked': true }" >{{$t("serviceDriveAuth['智慧教室授權管理']")}}<span class="title-checked-line"></span></span></div>
-      <Row>
-        <i-col :xs="24" :sm="24" :md="24" :lg="19">
-          <Row>
-            <i-col :xs="24" :sm="24" :md="24" :lg="13">
-              <div class="hiteach-info">
-                <p class="nomal-text">{{$t("serviceDriveAuth['Hiteach序號數']")}}</p>
-                <Row>
-                  <i-col :xs="24" :sm="24" :md="24" :lg="12">
-                    <p class="device-max">{{$t("serviceDriveAuth['大量']")}}</p>
-                    &nbsp;<span class="nomal-text">{{$t("serviceDriveAuth['授權']")}}</span>
-                    <p class="info-num-small">{{ serialInfo.multiAuthNum }}</p>
-                  </i-col>
-                  <i-col :xs="24" :sm="24" :md="24" :lg="12">
-                    <p class="device-max">{{$t("serviceDriveAuth['單一']")}}</p>
-                    &nbsp;<span class="nomal-text">{{$t("serviceDriveAuth['授權']")}}</span>
-                    <p class="info-num-small">{{ serialInfo.singleAuthNum }}</p>
-                  </i-col>
-                </Row>
+            <div slot="footer">
+                <Button type="text" @click="isOpenRemove = false">{{$t("serviceDriveAuth['取消']")}}</Button>
+                <Button type="primary" @click="removeUserPC(currentConfirmRemovePC)">{{$t("serviceDriveAuth['確定']")}}</Button>
+            </div>
+        </Modal>
+        <Loading v-if="isloading == true"></Loading>
+        <div class="service-list">
+            <div class="service-listTitle">
+                <span class="title-item" @click="setTab(1)" :class="{ 'title-checked': true }">
+                    {{$t("serviceDriveAuth['智慧教室授權管理']")}}
+                    <span class="title-checked-line">
+                    </span>
+                </span>
+                <span class="title-item" @click="setTab(0)">{{$t("serviceDriveAuth['服務授權列表']")}}</span>
+            </div>
+            <Row>
+                <i-col :xs="24" :sm="24" :md="24" :lg="19">
+                    <Row>
+                        <i-col :xs="24" :sm="24" :md="24" :lg="13">
+                            <div class="hiteach-info">
+                                <p class="nomal-text">{{$t("serviceDriveAuth['Hiteach序號數']")}}</p>
+                                <Row>
+                                    <i-col :xs="24" :sm="24" :md="24" :lg="12">
+                                        <p class="device-max">{{$t("serviceDriveAuth['大量']")}}</p>
+                                        &nbsp;<span class="nomal-text">{{$t("serviceDriveAuth['授權']")}}</span>
+                                        <p class="info-num-small">{{ serialInfo.multiAuthNum }}</p>
+                                    </i-col>
+                                    <i-col :xs="24" :sm="24" :md="24" :lg="12">
+                                        <p class="device-max">{{$t("serviceDriveAuth['單一']")}}</p>
+                                        &nbsp;<span class="nomal-text">{{$t("serviceDriveAuth['授權']")}}</span>
+                                        <p class="info-num-small">{{ serialInfo.singleAuthNum }}</p>
+                                    </i-col>
+                                </Row>
 
-                <!--p class="info-num">{{ serialInfo.totalNum }}</p-->
-              </div>
-            </i-col>
-            <i-col :xs="24" :sm="24" :md="24" :lg="5">
-              <div class="hiteach-info">
-                <p class="nomal-text">{{$t("serviceDriveAuth['可啟用裝置數']")}}</p>
-                <p class="info-num">
-                  {{ serialInfo.couldActiveNum }}
-                </p>
-              </div>
-            </i-col>
-            <i-col :xs="24" :sm="24" :md="24" :lg="6">
-              <div class="hiteach-info">
-                <p class="nomal-text">{{$t("serviceDriveAuth['已啟用裝置數']")}}</p>
-                <p class="info-num">
-                  {{ serialInfo.activeNum }}
-                </p>
-              </div>
-            </i-col>
-          </Row></i-col
-        >
-        <i-col :xs="24" :sm="24" :md="24" :lg="5">
-          <div class="action-btn" @click="gotoHiteachMgmt()">
-            {{$t("serviceDriveAuth['管理Hiteach教室']")}}
-          </div>
-        </i-col>
-      </Row>
-    </div>
-    <div class="hiteach-info-border" />
-    <div class="hiteach-type-filter">
-       <!--篩選選單-->
-      <Dropdown @on-click="filterList">
-        <a class="title" href="javascript:void(0)">
-          <span
-            v-for="item in filterListItem"
-            v-show="filterType == item.name"
-            :key="item.name"
-            >{{ item.text }}</span
-          >
+                                <!--p class="info-num">{{ serialInfo.totalNum }}</p-->
+                            </div>
+                        </i-col>
+                        <i-col :xs="24" :sm="24" :md="24" :lg="5">
+                            <div class="hiteach-info">
+                                <p class="nomal-text">{{$t("serviceDriveAuth['可啟用裝置數']")}}</p>
+                                <p class="info-num">
+                                    {{ serialInfo.couldActiveNum }}
+                                </p>
+                            </div>
+                        </i-col>
+                        <i-col :xs="24" :sm="24" :md="24" :lg="6">
+                            <div class="hiteach-info">
+                                <p class="nomal-text">{{$t("serviceDriveAuth['已啟用裝置數']")}}</p>
+                                <p class="info-num">
+                                    {{ serialInfo.activeNum }}
+                                </p>
+                            </div>
+                        </i-col>
+                    </Row>
+                </i-col>
+                <i-col :xs="24" :sm="24" :md="24" :lg="5">
+                    <div class="action-btn" @click="gotoHiteachMgmt()">
+                        {{$t("serviceDriveAuth['管理Hiteach教室']")}}
+                    </div>
+                </i-col>
+            </Row>
+        </div>
+        <div class="hiteach-info-border" />
+        <div class="hiteach-type-filter">
+            <!--篩選選單-->
+            <Dropdown @on-click="filterList">
+                <a class="title" href="javascript:void(0)">
+                    <span v-for="item in filterListItem" v-show="filterType == item.name" :key="item.name">{{ item.text }}</span>
 
-          <span><Icon type="ios-arrow-down"></Icon></span>
-        </a>
-        <DropdownMenu slot="list">
-          <DropdownItem
-            v-for="item in filterListItem"
-            :name="`${item.name}`"
-            :key="item.name"
-            >{{ item.text }}</DropdownItem
-          >
-        </DropdownMenu>
-      </Dropdown>
-    </div>
-    <div class="hiteach-list" :style="{ height: windowHeight - 250 + 'px' }">
-      <!--無資料時-->
-       <div
-        v-if="
+                    <span>
+                        <Icon type="ios-arrow-down"></Icon>
+                    </span>
+                </a>
+                <DropdownMenu slot="list">
+                    <DropdownItem v-for="item in filterListItem" :name="`${item.name}`" :key="item.name">{{ item.text }}</DropdownItem>
+                </DropdownMenu>
+            </Dropdown>
+        </div>
+        <div class="hiteach-list" :style="{ height: windowHeight - 250 + 'px' }">
+            <!--無資料時-->
+            <div v-if="
          serialInfo.multiAuthNum==0&& serialInfo.singleAuthNum==0
-        "
-        class="no-data-text"
-      >
-        <img src="../../../assets/icon/no_data.png" width="120" />
-        <p style="color: #808080">{{$t("serviceDriveAuth['暂无数据']")}}</p>
-      </div>
+        " class="no-data-text">
+                <img src="../../../assets/icon/no_data.png" width="120" />
+                <p style="color: #808080">{{$t("serviceDriveAuth['暂无数据']")}}</p>
+            </div>
 
+            <div class="hiteach-item" v-for="(i, index) in hiteachAuthList" :key="i.id" v-show="filterCondition(i)">
+                <div class="detail-btn" @click="setIntroOpen(index)" v-if="i.endDate != 1 && i.deviceBound.length != 0 && i.deviceMax != 1">
+                    <!--只要是單一就直接展開無需開關控件-->
+                    <Icon v-show="hiteachListItemIsOpen[index].isOpen == false" type="ios-arrow-down" />
+                    <Icon v-show="hiteachListItemIsOpen[index].isOpen == true" type="ios-arrow-up" />
+                </div>
+                <Row>
+                    <i-col :xs="24" :sm="24" :md="24" :lg="3">
+                        <div class="hicon-wrap">
+                            <v-icon v-if="i.prodCode === 'J223IZ6M'" iconClass="hiteach_std" />
+                            <v-icon v-if="i.prodCode === 'J223IZAM'" iconClass="hiteach_pro" />
+                            <v-icon v-if="i.prodCode === '3222C6D2'" iconClass="hiteach_tbl" />
+                        </div>
+                    </i-col>
+                    <i-col :xs="24" :sm="24" :md="24" :lg="21">
+                        <p class="title">
 
-      <div
-        class="hiteach-item"
-        v-for="(i, index) in hiteachAuthList"
-        :key="i.id"
-        v-show="filterCondition(i)"
-      >
-        <div
-          class="detail-btn"
-          @click="setIntroOpen(index)"
-          v-if="i.endDate != 1 && i.deviceBound.length != 0 && i.deviceMax != 1"
-        >
-          <!--只要是單一就直接展開無需開關控件-->
-          <Icon
-            v-show="hiteachListItemIsOpen[index].isOpen == false"
-            type="ios-arrow-down"
-          />
-          <Icon
-            v-show="hiteachListItemIsOpen[index].isOpen == true"
-            type="ios-arrow-up"
-          />
-        </div>
-        <Row>
-          <i-col :xs="24" :sm="24" :md="24" :lg="3">
-            <div class="hicon-wrap">
-              <v-icon
-                v-if="i.prodCode === 'J223IZ6M'" 
-                iconClass="hiteach_std"
-              /><v-icon
-                v-if="i.prodCode === 'J223IZAM'"
-                iconClass="hiteach_pro"
-              /><v-icon v-if="i.prodCode === '3222C6D2'" iconClass="hiteach_tbl" />
-            </div>
-          </i-col>
-          <i-col :xs="24" :sm="24" :md="24" :lg="21">
-            <p class="title">
-            
-              <span v-if="i.prodCode === 'J223IZ6M'" >HiTeach STD </span>
-              <span v-if="i.prodCode === '3222C6D2'" >HiTeach TBL </span>
-              <span v-if="i.prodCode === 'J223IZAM'" >HiTeach PRO </span>
-              <span class="device-max">{{
+                            <span v-if="i.prodCode === 'J223IZ6M'">HiTeach STD </span>
+                            <span v-if="i.prodCode === '3222C6D2'">HiTeach TBL </span>
+                            <span v-if="i.prodCode === 'J223IZAM'">HiTeach PRO </span>
+                            <span class="device-max">{{
                 i.deviceMax == 1 ? $t("serviceDriveAuth['單一']") : $t("serviceDriveAuth['大量']")
               }}</span>
-            </p>
-            <p
-              class="serial"
-              :class="{ 'overtime-text': i.expireStatus == 'F' }"
-            >
-              {{ i.serial }}
-            </p>
+                        </p>
+                        <p class="serial" :class="{ 'overtime-text': i.expireStatus == 'F' }">
+                            {{ i.serial }}
+                        </p>
 
-            <p class="app-group">
-              <span
-                v-for="(item, index) in aprules"
-                :key="index"
-                class="more-app"
-                :class="{
+                        <p class="app-group">
+                            <span v-for="(item, index) in aprules" :key="index" class="more-app" :class="{
                   'bought-app': i.aprule!=null&&i.aprule.hasOwnProperty(item) == true,
-                }"
-                >{{ $t("schoolBaseInfo." + item) }}</span
-              >
-             
-            </p>
-            <Row>
-              <i-col :xs="24" :sm="24" :md="24" :lg="7">
-                <p class="nomal-text">
-                  {{$t("serviceDriveAuth['序號到期日']") }}<span
-                    class="strong-text"
-                    v-if="i.expireStatus == 'A' || i.expireStatus === ''"
-                    >{{ i.endDate == 0 ?  $t("serviceDriveAuth['無到期日']")  : converTime(i.endDate) }}
-                  </span>
-                  <!--span  class="strong-text" v-if="i.expireStatus === ''">(未啟用)</span-->
-                  <span class="strong-text" v-if="i.expireStatus == 'F'"
-                    >{{$t("serviceDriveAuth['已到期']")}}</span
-                  >
-                </p>
-              </i-col>
-              <i-col :xs="24" :sm="24" :md="24" :lg="17"
-                ><p class="nomal-text" style="margin-left: 4%">
-                 {{$t("serviceDriveAuth['序號使用狀況']")}}<span class="strong-text"
-                    >{{ i.deviceBound.length }} / {{ i.deviceMax }} ({{
+                }">{{ $t("schoolBaseInfo." + item) }}</span>
+
+                        </p>
+                        <Row>
+                            <i-col :xs="24" :sm="24" :md="24" :lg="7">
+                                <p class="nomal-text">
+                                    {{$t("serviceDriveAuth['序號到期日']") }}<span class="strong-text" v-if="i.expireStatus == 'A' || i.expireStatus === ''">{{ i.endDate == 0 ?  $t("serviceDriveAuth['無到期日']")  : converTime(i.endDate) }}
+                                    </span>
+                                    <!--span  class="strong-text" v-if="i.expireStatus === ''">(未啟用)</span-->
+                                    <span class="strong-text" v-if="i.expireStatus == 'F'">{{$t("serviceDriveAuth['已到期']")}}</span>
+                                </p>
+                            </i-col>
+                            <i-col :xs="24" :sm="24" :md="24" :lg="17">
+                                <p class="nomal-text" style="margin-left: 4%">
+                                    {{$t("serviceDriveAuth['序號使用狀況']")}}<span class="strong-text">{{ i.deviceBound.length }} / {{ i.deviceMax }} ({{
                       (i.deviceBound.length > i.deviceMax
                         ? 100
                         : (i.deviceBound.length / i.deviceMax) * 100
                       ).toFixed(0) + "%"
-                    }})</span
-                  >
-                </p></i-col
-              >
-            </Row>
-          </i-col>
-        </Row>
-        <!--只要是單一就直接展開無需開關控件-->
-        <ul
-          class="pclist"
-          v-if="
+                    }})</span>
+                                </p>
+                            </i-col>
+                        </Row>
+                    </i-col>
+                </Row>
+                <!--只要是單一就直接展開無需開關控件-->
+                <ul class="pclist" v-if="
             (i.endDate != 1 && hiteachListItemIsOpen[index].isOpen == true) ||
             i.deviceMax == 1
-          "
-        >
-          <li
-            :id="`PC${pc.uuid != null ? pc.uuid : pc.uuid2}`"
-            v-for="(pc, index) in i.deviceBound"
-            :key="index + 'pc'"
-            v-show="i.deviceMax != 1 ? index < i.deviceMax : index < 1"
-            class="pclist-item"
-          >
-            <p class="pc-title">
-              {{ pc.pcname == null ? $t("serviceDriveAuth['未命名機台']") : pc.pcname }}
-            </p>
-            <p class="nomal-text" v-if="pc.ip!==null">
-              {{ pc.ip }} | {{ pc.uuid != null ? pc.uuid : pc.uuid2 }}
-            </p>
-             <p class="nomal-text" v-else>
-              {{ pc.uuid != null ? pc.uuid : pc.uuid2 }}
-            </p>
-            <p class="nomal-text" v-if="pc.os!==null">
-              {{ pc.os }}&nbsp;{{ pc.cpu }}&nbsp;{{
+          ">
+                    <li :id="`PC${pc.uuid != null ? pc.uuid : pc.uuid2}`" v-for="(pc, index) in i.deviceBound" :key="index + 'pc'" v-show="i.deviceMax != 1 ? index < i.deviceMax : index < 1" class="pclist-item">
+                        <p class="pc-title">
+                            {{ pc.pcname == null ? $t("serviceDriveAuth['未命名機台']") : pc.pcname }}
+                        </p>
+                        <p class="nomal-text" v-if="pc.ip!==null">
+                            {{ pc.ip }} | {{ pc.uuid != null ? pc.uuid : pc.uuid2 }}
+                        </p>
+                        <p class="nomal-text" v-else>
+                            {{ pc.uuid != null ? pc.uuid : pc.uuid2 }}
+                        </p>
+                        <p class="nomal-text" v-if="pc.os!==null">
+                            {{ pc.os }}&nbsp;{{ pc.cpu }}&nbsp;{{
                 (pc.ram / 1000).toFixed(1)
               }}G RAM
-            </p>
-            <div
-              class="action-btn"
-              @click="comfirmRemovePC(pc.uuid != null ? pc.uuid : pc.uuid2)"
-            >
-              <Icon type="md-close" /> {{$t("serviceDriveAuth['解除授權']")}}
+                        </p>
+                        <div class="action-btn" @click="comfirmRemovePC(pc.uuid != null ? pc.uuid : pc.uuid2)">
+                            <Icon type="md-close" /> {{$t("serviceDriveAuth['解除授權']")}}
+                        </div>
+                    </li>
+                    <!--div v-if="i.deviceBound==0" class='pclist-empty' >尚未綁定任何機台</div-->
+                </ul>
             </div>
-          </li>
-          <!--div v-if="i.deviceBound==0" class='pclist-empty' >尚未綁定任何機台</div-->
-        </ul>
-      </div>
+        </div>
     </div>
-  </div>
 </template>
 
 <script>
@@ -244,172 +184,172 @@ import "@/icons/svg/hiteach_std.svg";
 import "@/icons/svg/hiteach_pro.svg";
 import "@/icons/svg/hiteach_tbl.svg";
 import Loading from "@/common/Loading.vue";
-import { mapGetters,mapMutations } from "vuex";
+import { mapGetters, mapMutations } from "vuex";
 export default {
-  props: ["hiteachAuthList", "windowHeight", "windowWidth"],
-  name: "HiteachAuthList",
-  components: {
-    Loading,
-  },
-  data() {
-    return {
-     
-      tempRemovePCs: [], //暫存解綁的UserPC的Mac
-      hiteachListItemIsOpen: {},
-      filterType: "1",
-      currentConfirmRemovePC: "", //暫存讓使用者確認的UserPC
-      isOpenRemove: false,
-      isloading: false,
-    };
-  },
-  created() {
-    this.hiteachListItemIsOpen = this.hiteachListItemIsOpenVuex;
-  },
-  computed: {
-    ...mapGetters({
-      serialInfo: "serviceDriveAuth/getHiteachAuthListInfo",
-      aprules: "schoolBaseInfo/getAprules", //讀取周邊產品列表
-      hiteachListItemIsOpenVuex: "serviceDriveAuth/getHiteachListItemIsOpen",
-    }),
-    title:function(){
-      return this.$t('serviceDriveAuth["確定解除授權"]')
-    },
-    filterListItem:function(){
-      return [
-        {
-          name: 1,
-          text: this.$t('serviceDriveAuth["顯示全部"]'),
-        },
-        {
-          name: 2,
-          text: this.$t('serviceDriveAuth["僅顯示HiTeach STD序號"]'),
-        },
-        {
-          name: 3,
-          text: this.$t('serviceDriveAuth["僅顯示HiTeach PRO序號"]'),
-        },
-        {
-          name: 4,
-          text: this.$t('serviceDriveAuth["僅顯示HiTeach TBL序號"]'),
-        },
-        {
-          name: 5,
-          text: this.$t('serviceDriveAuth["僅顯示已完成綁定的序號"]'),
-        },
-        {
-          name: 6,
-          text: this.$t('serviceDriveAuth["僅顯示已到期序號"]'),
-        },
-      ]
-    }
-  },
-  watch: {
-    hiteachAuthList: function (value) {
-      //根據服務的長度生出開關,只要服務數量變動就必須重置
-     
-      let temp = [];
-
-      for (let i = 0; i < value.length; i++) {
-        temp.push({
-          index: i,
-          isOpen: false,
-        });
-      }
-      console.log(value, temp);
-      this.hiteachListItemIsOpen = temp;
+    props: ["hiteachAuthList", "windowHeight", "windowWidth"],
+    name: "HiteachAuthList",
+    components: {
+        Loading,
     },
-  },
-  methods: {
-    ...mapMutations({
-      setTab: 'serviceDriveAuth/setTab'
-    }),
+    data() {
+        return {
 
-    //先讓使用者確定是否解除授權
-    comfirmRemovePC(mac) {
-      this.isOpenRemove = true;
-      this.currentConfirmRemovePC = mac;
+            tempRemovePCs: [], //暫存解綁的UserPC的Mac
+            hiteachListItemIsOpen: {},
+            filterType: "1",
+            currentConfirmRemovePC: "", //暫存讓使用者確認的UserPC
+            isOpenRemove: false,
+            isloading: false,
+        };
     },
-    removeUserPC(mac) {
-      //假設回傳deviceMac,進行解綁動作
-      this.isOpenRemove = false;
-      if (this.tempRemovePCs.includes(mac) == false) {
-        this.tempRemovePCs.push(mac);
-      }
-      //console.log(this.tempRemovePCs);
-      document.getElementById(`PC${mac}`).classList.add("remove-pc");
-      setTimeout(() => {
-        document.getElementById(`PC${mac}`).style.display = "none";
-
-        this.$Message.success(this.$t('serviceDriveAuth["已成功解除授權"]'));
-      }, 1800);
-      this.isloading = true;
-      setTimeout(() => {
-        this.getDataAsyc();
-        this.isloading = false;
-      }, 3000);
+    created() {
+        this.hiteachListItemIsOpen = this.hiteachListItemIsOpenVuex;
     },
-    gotoHiteachMgmt() {
-      this.$router.push("/home/classroom");
-    },
-    getDataAsyc() {
-      this.$store.dispatch("serviceDriveAuth/getServiceListDataAsyc").then(
-        (res) => {
-          this.$Message.success("取得Mock資料");
+    computed: {
+        ...mapGetters({
+            serialInfo: "serviceDriveAuth/getHiteachAuthListInfo",
+            aprules: "schoolBaseInfo/getAprules", //讀取周邊產品列表
+            hiteachListItemIsOpenVuex: "serviceDriveAuth/getHiteachListItemIsOpen",
+        }),
+        title: function () {
+            return this.$t('serviceDriveAuth["確定解除授權"]')
         },
-        (err) => {
-          this.$Message.error("取得資料失敗");
+        filterListItem: function () {
+            return [
+                {
+                    name: 1,
+                    text: this.$t('serviceDriveAuth["顯示全部"]'),
+                },
+                {
+                    name: 2,
+                    text: this.$t('serviceDriveAuth["僅顯示HiTeach STD序號"]'),
+                },
+                {
+                    name: 3,
+                    text: this.$t('serviceDriveAuth["僅顯示HiTeach PRO序號"]'),
+                },
+                {
+                    name: 4,
+                    text: this.$t('serviceDriveAuth["僅顯示HiTeach TBL序號"]'),
+                },
+                {
+                    name: 5,
+                    text: this.$t('serviceDriveAuth["僅顯示已完成綁定的序號"]'),
+                },
+                {
+                    name: 6,
+                    text: this.$t('serviceDriveAuth["僅顯示已到期序號"]'),
+                },
+            ]
         }
-      );
     },
-    filterCondition(item) {
-      switch (this.filterType) {
-        case "1":
-          return true;
+    watch: {
+        hiteachAuthList: function (value) {
+            //根據服務的長度生出開關,只要服務數量變動就必須重置
 
-        case "2":
-          return item.prodCode === 'J223IZ6M'
-          //return item.prodName === "STD";
-        case "3":
-          return item.prodCode === 'J223IZAM'
-          //return item.prodName === "PRO";
-        case "4":
-           return item.prodCode === '3222C6D2'
-          //return item.prodName === "TBL";
-        case "5":
-          return item.deviceBound.length != 0;
-        case "6":
-          return item.expireStatus === "F";
+            let temp = [];
 
-        default:
-          return true;
-      }
-    },
-    filterList(name) {
-      this.filterType = name;
-    },
-    converTime: function (time) {
-      //time: Unix timestamp(秒)
-      let datetime = new Date();
-      //let timerecount = time * 1000 - datetime.getTimezoneOffset() * 60 * 1000;
-      let timerecount = time * 1000;
-      datetime.setTime(timerecount);
-      let year = datetime.getFullYear();
-      let month = datetime.getMonth() + 1;
-      let date = datetime.getDate();
-      let hour = datetime.getHours();
-      let ampm = hour >= 12 ? "PM" : "AM";
-      hour %= 12;
-      hour = hour || 12; // the hour '0' should be '12'
-      let minute = datetime.getMinutes();
-      return year + "." + month + "." + date;
+            for (let i = 0; i < value.length; i++) {
+                temp.push({
+                    index: i,
+                    isOpen: false,
+                });
+            }
+            console.log(value, temp);
+            this.hiteachListItemIsOpen = temp;
+        },
     },
-    setIntroOpen(index) {
-      this.hiteachListItemIsOpen[index].isOpen = !this.hiteachListItemIsOpen[
-        index
-      ].isOpen;
-      //console.log(index, this.hiteachListItemIsOpen);
+    methods: {
+        ...mapMutations({
+            setTab: 'serviceDriveAuth/setTab'
+        }),
+
+        //先讓使用者確定是否解除授權
+        comfirmRemovePC(mac) {
+            this.isOpenRemove = true;
+            this.currentConfirmRemovePC = mac;
+        },
+        removeUserPC(mac) {
+            //假設回傳deviceMac,進行解綁動作
+            this.isOpenRemove = false;
+            if (this.tempRemovePCs.includes(mac) == false) {
+                this.tempRemovePCs.push(mac);
+            }
+            //console.log(this.tempRemovePCs);
+            document.getElementById(`PC${mac}`).classList.add("remove-pc");
+            setTimeout(() => {
+                document.getElementById(`PC${mac}`).style.display = "none";
+
+                this.$Message.success(this.$t('serviceDriveAuth["已成功解除授權"]'));
+            }, 1800);
+            this.isloading = true;
+            setTimeout(() => {
+                this.getDataAsyc();
+                this.isloading = false;
+            }, 3000);
+        },
+        gotoHiteachMgmt() {
+            this.$router.push("/home/classroom");
+        },
+        getDataAsyc() {
+            this.$store.dispatch("serviceDriveAuth/getServiceListDataAsyc").then(
+                (res) => {
+                    this.$Message.success("取得Mock資料");
+                },
+                (err) => {
+                    this.$Message.error("取得資料失敗");
+                }
+            );
+        },
+        filterCondition(item) {
+            switch (this.filterType) {
+                case "1":
+                    return true;
+
+                case "2":
+                    return item.prodCode === 'J223IZ6M'
+                //return item.prodName === "STD";
+                case "3":
+                    return item.prodCode === 'J223IZAM'
+                //return item.prodName === "PRO";
+                case "4":
+                    return item.prodCode === '3222C6D2'
+                //return item.prodName === "TBL";
+                case "5":
+                    return item.deviceBound.length != 0;
+                case "6":
+                    return item.expireStatus === "F";
+
+                default:
+                    return true;
+            }
+        },
+        filterList(name) {
+            this.filterType = name;
+        },
+        converTime: function (time) {
+            //time: Unix timestamp(秒)
+            let datetime = new Date();
+            //let timerecount = time * 1000 - datetime.getTimezoneOffset() * 60 * 1000;
+            let timerecount = time * 1000;
+            datetime.setTime(timerecount);
+            let year = datetime.getFullYear();
+            let month = datetime.getMonth() + 1;
+            let date = datetime.getDate();
+            let hour = datetime.getHours();
+            let ampm = hour >= 12 ? "PM" : "AM";
+            hour %= 12;
+            hour = hour || 12; // the hour '0' should be '12'
+            let minute = datetime.getMinutes();
+            return year + "." + month + "." + date;
+        },
+        setIntroOpen(index) {
+            this.hiteachListItemIsOpen[index].isOpen = !this.hiteachListItemIsOpen[
+                index
+            ].isOpen;
+            //console.log(index, this.hiteachListItemIsOpen);
+        },
     },
-  },
 };
 </script>
 
@@ -417,30 +357,30 @@ export default {
 @import "./HiteachAuthList.less";
 
 #hiteachAuth-modal {
-  .ivu-modal-header {
-    border-radius: 5px 5px 0px 0px !important;
-  }
-  .ivu-modal-footer {
-    border-radius: 0px 0px 5px 5px !important;
-  }
+    .ivu-modal-header {
+        border-radius: 5px 5px 0px 0px !important;
+    }
+    .ivu-modal-footer {
+        border-radius: 0px 0px 5px 5px !important;
+    }
 
-  .ivu-modal-header,
-  .ivu-modal-body,
-  .ivu-modal-footer {
-    background-color: rgb(88, 88, 88) !important;
-    color: white !important;
-    border: none !important;
-  }
-  .ivu-btn-text {
-    color: white;
-    &:hover {
-      background-color: transparent !important;
-      color: #1cc0f3;
+    .ivu-modal-header,
+    .ivu-modal-body,
+    .ivu-modal-footer {
+        background-color: rgb(88, 88, 88) !important;
+        color: white !important;
+        border: none !important;
+    }
+    .ivu-btn-text {
+        color: white;
+        &:hover {
+            background-color: transparent !important;
+            color: #1cc0f3;
+        }
+    }
+    .ivu-modal-header-inner {
+        color: white !important;
+        font-weight: bolder !important;
     }
-  }
-  .ivu-modal-header-inner {
-    color: white !important;
-    font-weight: bolder !important;
-  }
 }
 </style>

+ 202 - 209
TEAMModelOS/ClientApp/src/view/serviceDriveAuth/SubComponents/ServiceList.vue

@@ -1,244 +1,237 @@
 <template>
-  <div class="service-list">
-    <div class="service-listTitle listTitle-noMargin"><span class="title-item" :class="{ 'title-checked': true }" @click="setTab(0)">{{$t("serviceDriveAuth['服務授權列表']")}}<span class="title-checked-line"></span></span> <span class="title-item" @click="setTab(1)">{{$t("serviceDriveAuth['智慧教室授權管理']")}}</span></div>
-    <div class="serviceList-wrap" :style="{ height: windowHeight - 116 + 'px' }">
-      <div class="service-item" v-for="(item, index) in serviceList" :key="index" v-show="item.prodCode != 'AEGMCPLY'">
-        <div class="detail-btn" @click="setIntroOpen(index)">
-          <Icon v-show="serviceIntroIsOpen[index].isOpen == false" type="ios-arrow-down" />
-          <Icon v-show="serviceIntroIsOpen[index].isOpen == true" type="ios-arrow-up" />
-        </div>
-        <div v-for="(proName, index) in serviceNameList" :key="index">
-          <p class="service-name" v-if="item.prodCode == proName && proName != 'AEGMCPLY'">
-            {{ $t(`serviceDriveAuth['${proName}']`) }}
-          </p>
+    <div class="service-list">
+        <div class="service-listTitle listTitle-noMargin">
+            <span class="title-item" @click="setTab(1)">{{$t("serviceDriveAuth['智慧教室授權管理']")}}</span>
+            <span class="title-item" :class="{ 'title-checked': true }" @click="setTab(0)">
+                {{$t("serviceDriveAuth['服務授權列表']")}}
+                <span class="title-checked-line"></span>
+            </span>
+
         </div>
-        <p class="unbuy" v-if="item.hasOwnProperty('notbuy') == true">{{$t("serviceDriveAuth['未購買']")}}</p>
-        <p class="isbuy" v-else>{{$t("serviceDriveAuth['已購買']")}}</p>
+        <div class="serviceList-wrap" :style="{ height: windowHeight - 116 + 'px' }">
+            <div class="service-item" v-for="(item, index) in serviceList" :key="index" v-show="item.prodCode != 'AEGMCPLY'">
+                <div class="detail-btn" @click="setIntroOpen(index)">
+                    <Icon v-show="serviceIntroIsOpen[index].isOpen == false" type="ios-arrow-down" />
+                    <Icon v-show="serviceIntroIsOpen[index].isOpen == true" type="ios-arrow-up" />
+                </div>
+                <div v-for="(proName, index) in serviceNameList" :key="index">
+                    <p class="service-name" v-if="item.prodCode == proName && proName != 'AEGMCPLY'">
+                        {{ $t(`serviceDriveAuth['${proName}']`) }}
+                    </p>
+                </div>
+                <p class="unbuy" v-if="item.hasOwnProperty('notbuy') == true">{{$t("serviceDriveAuth['未購買']")}}</p>
+                <p class="isbuy" v-else>{{$t("serviceDriveAuth['已購買']")}}</p>
 
-        <p class="nomal-text">
-          {{$t("serviceDriveAuth['服務啟用 / 到期日:']")}}
-          <span class="strong-text" v-if="item.startDate != 0 && item.prodCode != 'RYGVCPLY'">{{ converTime(item.startDate) }} - {{ converTime(item.endDate) }}</span>
-          <span class="strong-text" v-if="item.startDate == 0 && item.prodCode != 'RYGVCPLY'">--</span>
-          <span class="strong-text" v-if="item.prodCode == 'RYGVCPLY' && isNaN(aclassOneTimeLimitData.startDate) == false">{{ converTime(aclassOneTimeLimitData.startDate) }} - {{ converTime(aclassOneTimeLimitData.endDate) }}</span>
-        </p>
-        <div v-if="item.hasOwnProperty('notbuy') != true">
-          <Row class="time-bar-wrap">
-            <i-col :xs="24" :sm="24" :md="24" :lg="20" style="padding-right: 10px">
-              <div class="time-bar" v-if="item.startDate != 0"></div>
-              <div
-                class="remain-bar"
-                v-if="item.startDate != 0"
-                :style="{
+                <p class="nomal-text">
+                    {{$t("serviceDriveAuth['服務啟用 / 到期日:']")}}
+                    <span class="strong-text" v-if="item.startDate != 0 && item.prodCode != 'RYGVCPLY'">{{ converTime(item.startDate) }} - {{ converTime(item.endDate) }}</span>
+                    <span class="strong-text" v-if="item.startDate == 0 && item.prodCode != 'RYGVCPLY'">--</span>
+                    <span class="strong-text" v-if="item.prodCode == 'RYGVCPLY' && isNaN(aclassOneTimeLimitData.startDate) == false">{{ converTime(aclassOneTimeLimitData.startDate) }} - {{ converTime(aclassOneTimeLimitData.endDate) }}</span>
+                </p>
+                <div v-if="item.hasOwnProperty('notbuy') != true">
+                    <Row class="time-bar-wrap">
+                        <i-col :xs="24" :sm="24" :md="24" :lg="20" style="padding-right: 10px">
+                            <div class="time-bar" v-if="item.startDate != 0"></div>
+                            <div class="remain-bar" v-if="item.startDate != 0" :style="{
                   width: (dateRemain(today(), converTime(item.endDate)) / dateRemain(converTime(item.startDate), converTime(item.endDate))).toFixed(2) * 100 + '%',
                   'background-color': colorPercent(converTime(item.startDate), converTime(item.endDate)) ? '#ad3435' : '#1cc0f3'
-                }"
-              ></div>
-            </i-col>
-            <i-col :xs="24" :sm="24" :md="24" :lg="4" v-if="item.startDate != 0">
-              <span class="remainDay">{{$t("serviceDriveAuth['剩餘']")}}</span>
-              <span
-                class="remainDay-text"
-                :style="{
+                }"></div>
+                        </i-col>
+                        <i-col :xs="24" :sm="24" :md="24" :lg="4" v-if="item.startDate != 0">
+                            <span class="remainDay">{{$t("serviceDriveAuth['剩餘']")}}</span>
+                            <span class="remainDay-text" :style="{
                   color: colorPercent(converTime(item.startDate), converTime(item.endDate)) ? '#ad3435' : '#1cc0f3'
-                }"
-                >{{ dateRemain(today(), converTime(item.endDate)) }}</span
-              ><span class="remainDay">{{$t("serviceDriveAuth['天']")}}</span>
-            </i-col>
-          </Row>
-          <Row class="time-bar-wrap" v-if="isNaN(aclassOneTimeLimitData.startDate) == false">
-            <i-col :xs="24" :sm="24" :md="24" :lg="20" style="padding-right: 10px">
-              <div class="time-bar" v-if="item.prodCode == 'RYGVCPLY'"></div>
-              <div
-                class="remain-bar"
-                v-if="item.prodCode == 'RYGVCPLY'"
-                :style="{
+                }">{{ dateRemain(today(), converTime(item.endDate)) }}</span><span class="remainDay">{{$t("serviceDriveAuth['天']")}}</span>
+                        </i-col>
+                    </Row>
+                    <Row class="time-bar-wrap" v-if="isNaN(aclassOneTimeLimitData.startDate) == false">
+                        <i-col :xs="24" :sm="24" :md="24" :lg="20" style="padding-right: 10px">
+                            <div class="time-bar" v-if="item.prodCode == 'RYGVCPLY'"></div>
+                            <div class="remain-bar" v-if="item.prodCode == 'RYGVCPLY'" :style="{
                   width: (dateRemain(today(), converTime(aclassOneTimeLimitData.endDate)) / dateRemain(converTime(aclassOneTimeLimitData.startDate), converTime(aclassOneTimeLimitData.endDate))).toFixed(2) * 100 + '%',
                   'background-color': colorPercent(converTime(aclassOneTimeLimitData.startDate), converTime(aclassOneTimeLimitData.endDate)) ? '#ad3435' : '#1cc0f3'
-                }"
-              ></div>
-            </i-col>
+                }"></div>
+                        </i-col>
 
-            <i-col :xs="24" :sm="24" :md="24" :lg="4" v-if="item.prodCode == 'RYGVCPLY'">
-              <span class="remainDay">{{$t("serviceDriveAuth['剩餘']")}}</span>
-              <span
-                class="remainDay-text"
-                :style="{
+                        <i-col :xs="24" :sm="24" :md="24" :lg="4" v-if="item.prodCode == 'RYGVCPLY'">
+                            <span class="remainDay">{{$t("serviceDriveAuth['剩餘']")}}</span>
+                            <span class="remainDay-text" :style="{
                   color: colorPercent(converTime(aclassOneTimeLimitData.startDate), converTime(aclassOneTimeLimitData.endDate)) ? '#ad3435' : '#1cc0f3'
-                }"
-                >{{ dateRemain(today(), converTime(aclassOneTimeLimitData.endDate)) }}</span
-              ><span class="remainDay">{{$t("serviceDriveAuth['天']")}}</span>
-            </i-col>
-          </Row>
-        </div>
-        <!--給AclassOne-->
-        <div class="detailinfo-block" v-if="index == 0 && serviceIntroIsOpen[index].isOpen == true">
-          <Row>
-            <i-col :xs="24" :sm="24" :md="24" :lg="10">
-              <p class="nomal-text auth-num" v-if="item.hasOwnProperty('notbuy') == false">
-                {{$t("serviceDriveAuth['無週期授權數量']")}}:<span class="strong-text">{{ item.avaliable }}</span>
-              </p>
-            </i-col>
-            <i-col :xs="24" :sm="24" :md="24" :lg="14">
-              <p class="nomal-text auth-num" v-if="aclassOneTimeLimitData != ''">
-                {{$t("serviceDriveAuth['有週期授權數量']")}}:<span class="strong-text">{{ aclassOneTimeLimitData.avaliable }}</span>
-              </p></i-col
-            >
-          </Row>
-          <Row v-if="item.hasOwnProperty('notbuy') == false">
-            <i-col :xs="24" :sm="24" :md="24" :lg="10">
-              <div class="title-rec"></div>
-              <p class="nomal-text title-withRec">
-                 {{$t("serviceDriveAuth['固定分配數']")}}:<span class="strong-text">{{ item.staUsed }} ({{ ((item.staUsed / item.avaliable) * 100).toFixed(1) }}%)</span>
-              </p>
-              <br />
-              <div class="title-rec"></div>
-              <p class="nomal-text title-withRec">
-                 {{$t("serviceDriveAuth['動態分配數']")}}:<span class="strong-text">{{ item.dynUsed }} ({{ ((item.dynUsed / item.avaliable) * 100).toFixed(1) }}%)</span>
-              </p></i-col
-            >
-            <i-col :xs="24" :sm="24" :md="24" :lg="7">
-              <p class="nomal-text">
-                 {{$t("serviceDriveAuth['總使用率']")}}:<span class="strong-text"> {{ (((item.dynUsed + item.staUsed) / item.avaliable) * 100).toFixed(1) }}%</span>
-              </p></i-col
-            >
-            <i-col :xs="24" :sm="24" :md="24" :lg="7"> <AclassOneChart :less="item.dynUsed" :used="item.staUsed" :avaliable="item.avaliable"/></i-col>
-          </Row>
-          <p
-            v-if="item.hasOwnProperty('notbuy') == true"
-            class="detail"
-            :style="{
+                }">{{ dateRemain(today(), converTime(aclassOneTimeLimitData.endDate)) }}</span><span class="remainDay">{{$t("serviceDriveAuth['天']")}}</span>
+                        </i-col>
+                    </Row>
+                </div>
+                <!--給AclassOne-->
+                <div class="detailinfo-block" v-if="index == 0 && serviceIntroIsOpen[index].isOpen == true">
+                    <Row>
+                        <i-col :xs="24" :sm="24" :md="24" :lg="10">
+                            <p class="nomal-text auth-num" v-if="item.hasOwnProperty('notbuy') == false">
+                                {{$t("serviceDriveAuth['無週期授權數量']")}}:<span class="strong-text">{{ item.avaliable }}</span>
+                            </p>
+                        </i-col>
+                        <i-col :xs="24" :sm="24" :md="24" :lg="14">
+                            <p class="nomal-text auth-num" v-if="aclassOneTimeLimitData != ''">
+                                {{$t("serviceDriveAuth['有週期授權數量']")}}:<span class="strong-text">{{ aclassOneTimeLimitData.avaliable }}</span>
+                            </p>
+                        </i-col>
+                    </Row>
+                    <Row v-if="item.hasOwnProperty('notbuy') == false">
+                        <i-col :xs="24" :sm="24" :md="24" :lg="10">
+                            <div class="title-rec"></div>
+                            <p class="nomal-text title-withRec">
+                                {{$t("serviceDriveAuth['固定分配數']")}}:<span class="strong-text">{{ item.staUsed }} ({{ ((item.staUsed / item.avaliable) * 100).toFixed(1) }}%)</span>
+                            </p>
+                            <br />
+                            <div class="title-rec"></div>
+                            <p class="nomal-text title-withRec">
+                                {{$t("serviceDriveAuth['動態分配數']")}}:<span class="strong-text">{{ item.dynUsed }} ({{ ((item.dynUsed / item.avaliable) * 100).toFixed(1) }}%)</span>
+                            </p>
+                        </i-col>
+                        <i-col :xs="24" :sm="24" :md="24" :lg="7">
+                            <p class="nomal-text">
+                                {{$t("serviceDriveAuth['總使用率']")}}:<span class="strong-text"> {{ (((item.dynUsed + item.staUsed) / item.avaliable) * 100).toFixed(1) }}%</span>
+                            </p>
+                        </i-col>
+                        <i-col :xs="24" :sm="24" :md="24" :lg="7">
+                            <AclassOneChart :less="item.dynUsed" :used="item.staUsed" :avaliable="item.avaliable" />
+                        </i-col>
+                    </Row>
+                    <p v-if="item.hasOwnProperty('notbuy') == true" class="detail" :style="{
               'margin-top': item.hasOwnProperty('notbuy') != true ? '0px' : '10px'
-            }"
-          >
-            {{$t("serviceDriveAuth['詳細服務內容']")}}:
-          </p>
-          <Row v-if="item.hasOwnProperty('notbuy') == true">
-            <i-col :xs="24" :sm="24" :md="24" :lg="16"> <p class="intro-text">待提供</p></i-col>
-          </Row>
-          <div class="action-btn" @click="gotoStudentManagent()">
-            {{$t("serviceDriveAuth['管理AClassOne授權']")}}:
-          </div>
-        </div>
+            }">
+                        {{$t("serviceDriveAuth['詳細服務內容']")}}:
+                    </p>
+                    <Row v-if="item.hasOwnProperty('notbuy') == true">
+                        <i-col :xs="24" :sm="24" :md="24" :lg="16">
+                            <p class="intro-text">待提供</p>
+                        </i-col>
+                    </Row>
+                    <div class="action-btn" @click="gotoStudentManagent()">
+                        {{$t("serviceDriveAuth['管理AClassOne授權']")}}:
+                    </div>
+                </div>
 
-        <!--給其他產品-->
-        <div class="detailinfo-block" v-if="index != 0 && serviceIntroIsOpen[index].isOpen == true">
-          <p class="detail" :style="{ 'margin-top': item.hasOwnProperty('notbuy') != true ? '0px' : '10px' }">
-            {{$t("serviceDriveAuth['詳細服務內容']")}}:
-          </p>
-          <Row>
-            <i-col :xs="24" :sm="24" :md="24" :lg="16"> <p class="intro-text">待提供</p></i-col>
-          </Row>
+                <!--給其他產品-->
+                <div class="detailinfo-block" v-if="index != 0 && serviceIntroIsOpen[index].isOpen == true">
+                    <p class="detail" :style="{ 'margin-top': item.hasOwnProperty('notbuy') != true ? '0px' : '10px' }">
+                        {{$t("serviceDriveAuth['詳細服務內容']")}}:
+                    </p>
+                    <Row>
+                        <i-col :xs="24" :sm="24" :md="24" :lg="16">
+                            <p class="intro-text">待提供</p>
+                        </i-col>
+                    </Row>
+                </div>
+            </div>
         </div>
-      </div>
     </div>
-  </div>
 </template>
 
 <script>
 
 import AclassOneChart from './AclassOneChart'
-import { mapGetters,mapMutations } from 'vuex'
+import { mapGetters, mapMutations } from 'vuex'
 export default {
-  props: ['serviceList', 'windowWidth', 'windowHeight'],
-  name: 'ServiceList',
-  data() {
-    return {
-      serviceIntroIsOpen: {},
-      oriIndex: '',
-      aclassOneTimeLimitData: ''
-    }
-  },
-  components: {
-    AclassOneChart
-  },
-  computed: {
-    ...mapGetters({
-      serviceIntroIsOpenVuex: 'serviceDriveAuth/getServiceIntroIsOpen',
-      serviceNameList: 'serviceDriveAuth/getServiceNameList'
-    })
-  },
-  created() {
-    this.serviceIntroIsOpen = this.serviceIntroIsOpenVuex
-  },
-
-  watch: {
-    serviceList: function() {
-      //根據服務的長度生出開關,只要服務數量變動就必須重置
-      let temp = []
-
-      for (let i = 0; i < this.serviceList.length; i++) {
-        temp.push({
-          index: i,
-          isOpen: false
-        })
-        temp[0].isOpen = true //預設把AclassOne細節打開
-        if (this.serviceList[i].prodCode == 'AEGMCPLY' && this.serviceList[i].hasOwnProperty('notbuy') != true) {
-          //console.log(this.serviceList[i])
-          this.aclassOneTimeLimitData = this.serviceList[i]
+    props: ['serviceList', 'windowWidth', 'windowHeight'],
+    name: 'ServiceList',
+    data() {
+        return {
+            serviceIntroIsOpen: {},
+            oriIndex: '',
+            aclassOneTimeLimitData: ''
         }
-      }
-      this.serviceIntroIsOpen = temp
-    }
-  },
-  beforeRouteLeave(to, from, next) {
-    this.setTab(0)
-    next()
-  },
-  methods: {
-    ...mapMutations({
-      setTab: 'serviceDriveAuth/setTab'
-    }),
-    converTime: function(time) {
-      //time: Unix timestamp(秒)
-      let datetime = new Date()
-      //let timerecount = time * 1000 - datetime.getTimezoneOffset() * 60 * 1000;
-      let timerecount = time * 1000
-      datetime.setTime(timerecount)
-      let year = datetime.getFullYear()
-      let month = datetime.getMonth() + 1
-      let date = datetime.getDate()
-      let hour = datetime.getHours()
-      let ampm = hour >= 12 ? 'PM' : 'AM'
-      hour %= 12
-      hour = hour || 12 // the hour '0' should be '12'
-      let minute = datetime.getMinutes()
-      return year + '.' + month + '.' + date
     },
-    gotoStudentManagent() {
-      this.$router.push('/home/studentAccount')
+    components: {
+        AclassOneChart
     },
-    colorPercent: function(a, b) {
-      if (this.dateRemain(this.today(), b) / this.dateRemain(a, b) < 0.3) return true
-      else return false
+    computed: {
+        ...mapGetters({
+            serviceIntroIsOpenVuex: 'serviceDriveAuth/getServiceIntroIsOpen',
+            serviceNameList: 'serviceDriveAuth/getServiceNameList'
+        })
     },
-    setIntroOpen(index) {
-      this.serviceIntroIsOpen[index].isOpen = !this.serviceIntroIsOpen[index].isOpen
-      //console.log(index, this.serviceIntroIsOpen);
+    created() {
+        this.serviceIntroIsOpen = this.serviceIntroIsOpenVuex
     },
-    today() {
-      var today = new Date()
-      var dd = String(today.getDate()).padStart(2, '0')
-      var mm = String(today.getMonth() + 1).padStart(2, '0') //January is 0!
-      var yyyy = today.getFullYear()
 
-      today = yyyy + '/' + mm + '/' + dd
-      return today
+    watch: {
+        serviceList: function () {
+            //根據服務的長度生出開關,只要服務數量變動就必須重置
+            let temp = []
+
+            for (let i = 0; i < this.serviceList.length; i++) {
+                temp.push({
+                    index: i,
+                    isOpen: false
+                })
+                temp[0].isOpen = true //預設把AclassOne細節打開
+                if (this.serviceList[i].prodCode == 'AEGMCPLY' && this.serviceList[i].hasOwnProperty('notbuy') != true) {
+                    //console.log(this.serviceList[i])
+                    this.aclassOneTimeLimitData = this.serviceList[i]
+                }
+            }
+            this.serviceIntroIsOpen = temp
+        }
     },
-    dateRemain(today, endday) {
-      let strEndday = endday.replace('.', '/')
+    beforeRouteLeave(to, from, next) {
+        this.setTab(0)
+        next()
+    },
+    methods: {
+        ...mapMutations({
+            setTab: 'serviceDriveAuth/setTab'
+        }),
+        converTime: function (time) {
+            //time: Unix timestamp(秒)
+            let datetime = new Date()
+            //let timerecount = time * 1000 - datetime.getTimezoneOffset() * 60 * 1000;
+            let timerecount = time * 1000
+            datetime.setTime(timerecount)
+            let year = datetime.getFullYear()
+            let month = datetime.getMonth() + 1
+            let date = datetime.getDate()
+            let hour = datetime.getHours()
+            let ampm = hour >= 12 ? 'PM' : 'AM'
+            hour %= 12
+            hour = hour || 12 // the hour '0' should be '12'
+            let minute = datetime.getMinutes()
+            return year + '.' + month + '.' + date
+        },
+        gotoStudentManagent() {
+            this.$router.push('/home/studentAccount')
+        },
+        colorPercent: function (a, b) {
+            if (this.dateRemain(this.today(), b) / this.dateRemain(a, b) < 0.3) return true
+            else return false
+        },
+        setIntroOpen(index) {
+            this.serviceIntroIsOpen[index].isOpen = !this.serviceIntroIsOpen[index].isOpen
+            //console.log(index, this.serviceIntroIsOpen);
+        },
+        today() {
+            var today = new Date()
+            var dd = String(today.getDate()).padStart(2, '0')
+            var mm = String(today.getMonth() + 1).padStart(2, '0') //January is 0!
+            var yyyy = today.getFullYear()
+
+            today = yyyy + '/' + mm + '/' + dd
+            return today
+        },
+        dateRemain(today, endday) {
+            let strEndday = endday.replace('.', '/')
 
-      //console.log(today, strEndday);
+            //console.log(today, strEndday);
 
-      let oDate1 = new Date(today)
-      let oDate2 = new Date(strEndday)
-      let iDays = parseInt(Math.abs(oDate1 - oDate2) / 1000 / 60 / 60 / 24) // 把相差的毫秒數轉換為天數
-      //console.log(iDays);
-      return iDays
+            let oDate1 = new Date(today)
+            let oDate2 = new Date(strEndday)
+            let iDays = parseInt(Math.abs(oDate1 - oDate2) / 1000 / 60 / 60 / 24) // 把相差的毫秒數轉換為天數
+            //console.log(iDays);
+            return iDays
+        }
     }
-  }
 }
 </script>
 
 <style lang="less">
-@import './ServiceList.less';
+@import "./ServiceList.less";
 </style>

+ 80 - 19
TEAMModelOS/ClientApp/src/view/settings/BaseApplyForm.vue

@@ -1,19 +1,29 @@
 <template>
 	<div>
 		<Form ref="applyForm" :model="applyForm" :rules="ruleValidate" label-position="top" class="apply-form">
-			<FormItem label="学校名称" prop="name">
-				<Input v-model="applyForm.name"></Input>
+			<FormItem :label="$t('settings.applyForm.name')" prop="name">
+				<Input v-model="applyForm.name" :placeholder="$t('settings.applyForm.place1')"></Input>
 			</FormItem>
-			<FormItem label="学校简码" prop="id">
+			<!-- <FormItem label="学校简码" prop="id">
 				<Input v-model="applyForm.id"></Input>
 			</FormItem>
 			<FormItem label="学校代码" prop="code">
 				<Input v-model="applyForm.code"></Input>
+			</FormItem> -->
+			<FormItem :label="$t('settings.applyForm.address')">
+				<BaseAreaPicker ref="areaPicker" v-if="isChinaSite"></BaseAreaPicker>
+				<div class="country-select" v-if="!isChinaSite">
+					<Select v-model="curCountry" filterable placeholder="选择学校所在地区">
+						<Option v-for="(country,index) in countryArr" :value="country.cn" :key="index" >{{ country.cn }}</Option>
+					</Select>
+				</div>
+				<Input type="textarea" :autosize="{minRows: 3,maxRows: 5}" v-model="applyForm.address" :placeholder="$t('settings.applyForm.place2')"></Input>
 			</FormItem>
-			<FormItem label="学校位置">
-				<!-- <Input v-model="applyForm.region"></Input> -->
-				<BaseAreaPicker ref="areaPicker"></BaseAreaPicker>
-				<Input type="textarea" :autosize="{minRows: 3,maxRows: 5}" v-model="applyForm.address"></Input>
+			<FormItem :label="$t('settings.applyForm.cellphone')" prop="cellphone">
+				<Input v-model="applyForm.cellphone" :placeholder="$t('settings.applyForm.place3')"></Input>
+			</FormItem>
+			<FormItem :label="$t('settings.applyForm.content')" prop="content">
+				<Input type="textarea" :autosize="{minRows: 3,maxRows: 5}" v-model="applyForm.content" :placeholder="$t('settings.applyForm.place4')"></Input>
 			</FormItem>
 			<!-- <FormItem label="学校图标">
 				<Upload v-if="!isPreview" ref="upload" :show-upload-list="false" :on-success="handleSuccess"
@@ -32,15 +42,19 @@
 				</div>
 			</FormItem> -->
 		</Form>
-		<Button style="background-color: #168794;width: 90%;margin-left: 5%;" @click="onSubmit">提交申请</Button>
+		<Button style="background-color: #168794;width: 90%;margin-left: 5%;" @click="onSubmit" :loading="isBtnLoading">{{ $t('settings.applyForm.submit') }}</Button>
 	</div>
 </template>
 
 <script>
+	import countries from '@/static/countries.js'
 	export default {
 		data() {
 			return {
+				isBtnLoading:false,
 				isPreview: false,
+				curCountry:'',
+				countryArr:[],
 				applyForm: {
 					id: '',
 					code: '',
@@ -49,7 +63,9 @@
 					province: '',
 					city: '',
 					picture: '',
-					address:''
+					address:'',
+					cellphone:'',
+					content:''
 				},
 				uploadList: [],
 				ruleValidate: {
@@ -68,21 +84,51 @@
 						message: '学校代码不能为空 ',
 						trigger: 'blur'
 					}],
+					cellphone: [{
+						required: true,
+						message: '联系方式不能为空 ',
+						trigger: 'blur'
+					}],
 				}
 			}
 		},
+		created() {
+			this.countryArr = countries
+		},
 		methods: {
+			// 提交建立学校申请
 			onSubmit() {
 				this.$refs.applyForm.validate((valid) => {
 					if (valid) {
 						let pickResult = this.$refs.areaPicker.pickResult
 						if(pickResult.province && pickResult.city && pickResult.area){
-							
+							this.isBtnLoading = true
+							let formInfo = this.applyForm
+							let params = {
+								name:formInfo.name,
+								area:pickResult.province + pickResult.city + pickResult.area + formInfo.address,
+								tmdname:this.$store.state.userInfo.name,
+								tmdid:this.$store.state.userInfo.TEAMModelId,
+								cellphone:formInfo.cellphone,
+								content:formInfo.content
+							}
+							this.$api.schoolSetting.applySchool(params).then(res => {
+								if(!res.error){
+									setTimeout(()=> {
+										this.isBtnLoading = false
+										this.$emit('applySuc')
+										this.$Message.success(this.$t('settings.applyForm.submitSuc'))
+									},1000)
+								}
+							}).catch(err => {
+								this.$Message.error(err)
+								this.isBtnLoading = false
+							})
 						}else{
-							this.$Message.error('请选择正确的省市区!');
+							this.$Message.error(this.$t('settings.applyForm.errTip1'));
 						}
 					} else {
-						this.$Message.error('请将信息填写完整!');
+						this.$Message.error(this.$t('settings.applyForm.errTip2'));
 					}
 				})
 			},
@@ -91,15 +137,20 @@
 				this.applyForm.picture = res.url
 				this.isPreview = true
 			},
-			handleFormatError(file) {
-				this.$Message.error('上传文件格式只能是jpg、jpeg、png!')
-			},
-			handleMaxSize(file) {
-				this.$Message.error('上传文件大小不能超过10M!')
-			},
+			// handleFormatError(file) {
+			// 	this.$Message.error('上传文件格式只能是jpg、jpeg、png!')
+			// },
+			// handleMaxSize(file) {
+			// 	this.$Message.error('上传文件大小不能超过10M!')
+			// },
 			handleBeforeUpload() {
 
 			}
+		},
+		computed:{
+			isChinaSite(){
+				return this.$store.state.config.srvAdr === 'China'
+			}
 		}
 	}
 </script>
@@ -107,6 +158,15 @@
 <style lang="less">
 	.apply-form {
 		padding: 50px 20px;
+		
+		.country-select{
+			width: 200px;
+			margin: 10px 0;
+		}
+		
+		.ivu-select-input{
+			color: #DDDDDD;
+		}
 
 		.ivu-form-item-label {
 			color: #bbb;
@@ -118,11 +178,12 @@
 			background: #575757;
 			border-color: transparent;
 			height: 35px;
+			padding: 10px;
 			color: #fff;
 		}
 
 		.ivu-input::-webkit-input-placeholder {
-			color: #808080;
+			color: #a8a8a8;
 		}
 
 		.ivu-select-single .ivu-select-selection {

+ 11 - 1
TEAMModelOS/ClientApp/src/view/settings/Index.less

@@ -4,10 +4,15 @@
 	height: 100%;
 	display: flex;
 	flex-direction: column;
+	/* background-color: #ffffff;
+	margin: 15px 20px;
+	border-radius: 5px;
+	box-shadow: 0px 0px 10px 2px #ccc; */
 	
 	.settings-header{
 		height: 70px;
 		border-bottom: 1px solid @border-color;
+		// border-bottom: 1px solid #909090;
 		
 		&-item{
 			display: inline-block;
@@ -15,7 +20,9 @@
 			line-height: 40px;
 			margin-top: 15px;
 			margin-left: 50px;
-			color:@label-textColor;
+			color: @label-textColor;
+			// color: #1E1F21;
+			// color: #909090;
 			cursor: pointer;
 			
 			&:first-child{
@@ -26,7 +33,10 @@
 		.active-item{
 			font-size: 14px;
 			color:#fff;
+			// color:#1CC0F3;
+			// color:#393b3c;
 			border-bottom: 2px solid @primary-color;
+			// border-bottom: 2px solid #393b3c;
 		}
 	}
 	

+ 2 - 2
TEAMModelOS/ClientApp/src/view/settings/Index.vue

@@ -20,14 +20,14 @@
                         <Checkbox v-model="cloudSetting.isSystemLang" @on-change="onMenuStatusChange">{{ $t('settings.langCheck')}}</Checkbox>
                     </span>
                 </div>
-                <div class="normal-settings-item">
+                <!-- <div class="normal-settings-item">
                     <span class="item-title">{{ $t('settings.themeSetting')}}</span>
                     <span class="item-description">{{ $t('settings.themeTips')}}</span>
                     <span class="item-content">
                         <span :class="['color-item',cloudSetting.curTheme === 'dark' ?  'color-item-active' : '']" @click="onTips('dark')"></span>
                         <span :class="['color-item',cloudSetting.curTheme === 'light' ?  'color-item-active' : '']" @click="onTips('light')"></span>
                     </span>
-                </div>
+                </div> -->
                 <div class="normal-settings-item">
                     <span class="item-title">{{ $t('settings.menuSetting')}}</span>
                     <span class="item-description">{{ $t('settings.menuTips')}}</span>

+ 12 - 10
TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.css

@@ -59,7 +59,11 @@
 .open-mgmt .open-mgmt-right .open-right-info .open-info {
   width: 30%;
   font-size: 16px;
-  /* .ivu-radio-wrapper{
+  /* .ivu-input{
+                    font-size: 16px;
+                    color: #525B6F;
+                }
+                .ivu-radio-wrapper{
                     color: #525B6F;
                 } */
 }
@@ -83,9 +87,6 @@
   top: -33px;
   right: 0;
 }
-.open-mgmt .open-mgmt-right .open-right-info .open-info .ivu-input {
-  font-size: 16px;
-}
 .open-mgmt .open-mgmt-right .open-right-info .open-info .open-info-disabled .ivu-input {
   background: transparent;
   border: none;
@@ -116,12 +117,13 @@
 .open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-page {
   float: right;
   margin-top: 15px;
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-page .ivu-page-item-active {
-  background-color: #BFBFB9 !important;
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-page .ivu-page-item-active a {
-  color: #595959;
+  /* .ivu-page-item-active{
+                        background-color: #BFBFB9 !important;
+                    }
+
+                    .ivu-page-item-active a{
+                        color: #595959;
+                    } */
 }
 .open-list,
 .open-header,

+ 5 - 6
TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.less

@@ -21,7 +21,6 @@
     .open-mgmt-left{
         width: 20%;
 
-        
         .open-left-list{
             margin-left: 10px;
 
@@ -102,11 +101,11 @@
                     }
                 }
 
-                .ivu-input{
+                /* .ivu-input{
                     font-size: 16px;
-                    // color: #525B6F;
+                    color: #525B6F;
                 }
-                /* .ivu-radio-wrapper{
+                .ivu-radio-wrapper{
                     color: #525B6F;
                 } */
 
@@ -152,13 +151,13 @@
                     float: right;
                     margin-top: 15px;
                     
-                    .ivu-page-item-active{
+                    /* .ivu-page-item-active{
                         background-color: #BFBFB9 !important;
                     }
 
                     .ivu-page-item-active a{
                         color: #595959;
-                    }
+                    } */
                 }
 
                 

+ 6 - 23
TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.vue

@@ -48,16 +48,9 @@
             <div class="open-right-info">
                 <div class="open-info">
                     <vuescroll>
-                        <!-- 基本信息 -->
-                        <!-- <div class="open-info-header">
-                            <span>基本信息</span>
-                        </div> -->
-                        <div class="dark-iview-form disabled-iview-input">
-                            <div class="open-mgmt-info">
+                        <div class="open-mgmt-info dark-iview-form disabled-iview-input">
+                            <!-- <div class="open-mgmt-info"> -->
                                 <Form :model="openMgInfo" label-position="top">
-                                    <!-- <FormItem label="授权学校">
-                                        <Input v-model="openMgInfo.school" class="open-info-disabled" readonly></Input>
-                                    </FormItem> -->
                                     <FormItem :label="$t('settings.openName')">
                                         <Input v-model="openMgInfo.name"
                                             :class="isEdit ? '' : 'open-info-disabled'"
@@ -66,12 +59,11 @@
                                     <FormItem :label="$t('settings.token')" class="api-token" v-show="!isEdit">
                                         <div class="api-icon">
                                             <!-- 隐藏 -->
-                                            <Icon :type="isTokenShow ? 'md-eye' : 'md-eye-off'" size="18" style="margin-right: 10px" color="#0094FF" @click="isTokenShow = !isTokenShow" />
-                                            <!-- <Icon type="md-eye" size="18" style="margin-right: 10px" color="#0094FF" /> -->
+                                            <Icon :type="isTokenShow ? 'md-eye' : 'md-eye-off'" size="18" style="margin-right: 10px" color="rgb(115 115 115)" @click="isTokenShow = !isTokenShow" />
                                             <!-- 刷新 -->
-                                            <Icon type="md-refresh" size="18" style="margin-right: 10px" color="#0094FF" @click="refresh" />
+                                            <Icon type="md-refresh" size="18" style="margin-right: 10px" color="rgb(115 115 115)" @click="refresh" />
                                             <!-- 复制 -->
-                                            <Icon type="ios-copy" size="18" color="#0094FF" @click="copyToken" />
+                                            <Icon type="ios-copy" size="18" color="rgb(115 115 115)" @click="copyToken" />
                                         </div>
                                         <Input
                                             v-model="openMgInfo.token"
@@ -97,15 +89,11 @@
                                     </FormItem>
                                 </Form>
                             </div>
-                        </div>
+                        <!-- </div> -->
                     </vuescroll>
                 </div>
                 <div class="open-api dark-iview-table dark-iview-page">
                 <!-- <div class="open-api"> -->
-                    <!-- Api列表 -->
-                    <!-- <div class="open-api-header">
-                        <span>Api列表</span>
-                    </div> -->
                     <vuescroll>
                         <div class="open-api-table">
                             <Table ref="selection"
@@ -416,11 +404,6 @@ export default {
             }
         },
         selectionChange(selection) {
-            /* selection.map(item => {
-                if(!item._checked) {
-                    item._checked = true
-                }
-            }) */
             this.apiListNow = selection
             console.log(selection);
         }

+ 123 - 0
TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.css

@@ -0,0 +1,123 @@
+.school-container {
+  display: flex;
+  height: 100%;
+  font-family: 'NotoSerif', '微软正黑体', 'Microsoft JhengHei UI', 'Microsoft JhengHei', Sans-serif;
+}
+.school-container .school-container-header {
+  display: flex;
+  justify-content: space-between;
+  padding-right: 20px;
+  color: #949494;
+}
+.school-container-left {
+  width: 28%;
+  height: 100%;
+  border-right: 1px solid #424242;
+}
+.school-container-left .school-list-wrap {
+  height: 100%;
+  overflow: hidden;
+}
+.school-container-left .school-list-wrap .list-wrap {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  padding-left: 10px;
+  padding-bottom: 50px;
+  overflow: hidden;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item {
+  position: relative;
+  width: 100%;
+  padding: 10px;
+  border-bottom: 1px solid #424242;
+  display: flex;
+  font-size: 12px;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item-name {
+  font-size: 14px;
+  font-weight: 300;
+  color: #fff;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item-status {
+  font-size: 12px;
+  background: #1CC0F3;
+  padding: 2px 8px;
+  margin-left: 10px;
+  border-radius: 2px;
+  font-weight: 200;
+  color: white;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item-code {
+  margin: 5px 0;
+  color: #a5a5a5;
+  letter-spacing: 0.6px;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item-nums {
+  color: #1CC0F3;
+  margin-top: 5px;
+  font-size: 12px;
+  margin-left: 20px;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item-nums .ivu-icon {
+  font-size: 18px;
+  margin-right: 5px;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item-role {
+  position: absolute;
+  right: 20px;
+  top: 20px;
+  color: #a5a5a5;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item-btn {
+  position: absolute;
+  right: 20px;
+  bottom: 20px;
+  height: 30px;
+  line-height: 30px;
+  border-radius: 5px;
+  color: #fff;
+  text-align: center;
+  cursor: pointer;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item-btn .ivu-icon {
+  font-size: 16px;
+  margin-right: 2px;
+  color: #DDDDDD;
+}
+.school-container-left .school-list-wrap .list-wrap .school-item:hover {
+  background-image: -webkit-linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+  background-image: -o-linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+  background-image: -moz-linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+  background-image: linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+}
+.school-container-left .school-list-wrap .list-wrap .school-item:hover .school-item-btn {
+  visibility: visible;
+}
+.school-container .schoolmgmt-container-right {
+  flex: 1;
+  height: 100%;
+}
+.school-container .schoolmgmt-container-right .school-container-header {
+  width: 100%;
+  height: 40px;
+  border-bottom: 1px solid #424242;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0 20px;
+}
+.school-container-header {
+  width: 100%;
+  height: 40px;
+  line-height: 40px;
+  padding-left: 20px;
+  color: #a5a5a5;
+  border-bottom: 1px solid #424242;
+}
+.school-container .item-active {
+  background-image: -webkit-linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+  background-image: -o-linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+  background-image: -moz-linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+  background-image: linear-gradient(90deg, rgba(30, 30, 30, 0) 0%, rgba(110, 110, 110, 0.2) 50%, rgba(110, 110, 110, 0.4) 100%);
+}

+ 6 - 0
TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.less

@@ -18,6 +18,7 @@
 		width: 28%;
 		height: 100%;
 		border-right: 1px solid @borderColor;
+		// border-right: 1px solid #909090;
 		
 		.school-list-wrap{
 			height: 100%;
@@ -36,6 +37,7 @@
 					width: 100%;
 					padding: 10px;
 					border-bottom: 1px solid @borderColor;
+					// border-bottom: 1px solid #e1e1e1;
 					display: flex;
 					font-size: 12px;
 					
@@ -47,6 +49,8 @@
 						font-size: 14px;
 						font-weight: 300;
 						color:#fff;
+
+						// color:#525B6F;
 					}
 					
 					&-status{
@@ -56,6 +60,7 @@
 						margin-left: 10px;
 						border-radius: 2px;
 						font-weight: 200;
+						color: white;
 					}
 					
 					&-code{
@@ -125,6 +130,7 @@
 			width: 100%;
 			height: 40px;
 			border-bottom: 1px solid @borderColor;
+			// border-bottom: 1px solid #909090;
 			display: flex;
 			align-items: center;
 			justify-content: space-between;

+ 2 - 1
TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.vue

@@ -117,7 +117,7 @@
 
 		<Modal v-model="applyModal" class-name="go-school-modal" footer-hide width="500">
 			<span class="apply-title">申请建立学校</span>
-			<BaseApplyForm></BaseApplyForm>
+			<BaseApplyForm @applySuc="applyModal = false"></BaseApplyForm>
 		</Modal>
 
 	</div>
@@ -442,6 +442,7 @@
 			&-tip {
 				span {
 					color: #fff;
+					// color: #010101;
 					font-weight: bold;
 					margin: 0 10px;
 				}

+ 1 - 1
TEAMModelOS/ClientApp/src/view/student-account/ImportStudent.vue

@@ -12,7 +12,7 @@
             </Upload>
             <p class="import-tips" style="margin-top:40px;">{{$t('stuAccount.importTips1')}}</p>
             <p class="import-tips">{{$t('stuAccount.importTips2') + $t('stuAccount.importTips3')}}</p>
-            <a style="margin-top:10px;color:turquoise;display:inline-block;" href="https://teammodelstorage.blob.core.chinacloudapi.cn/download/%E5%AD%A6%E7%94%9F%E5%90%8D%E5%8D%95%E6%A8%A1%E5%9D%97.xlsx">(下载名单模板)</a>
+            <a style="margin-top:10px;color:turquoise;display:inline-block;" href="https://teammodelstorage.blob.core.chinacloudapi.cn/download/%E5%AD%A6%E7%94%9F%E5%90%8D%E5%8D%95%E6%A8%A1%E5%9D%97.xlsx">{{$t('stuAccount.downloadText')}}</a>
         </div>
         <div class="form-body" style="background:none;" v-else>
             <div class="ivu-upload-list-file">

+ 3 - 7
TEAMModelOS/ClientApp/src/view/student-account/Index.vue

@@ -12,18 +12,14 @@
         <div class="stu-mgt-header">
             <div class="tab-box">
                 <span class="pane" @click="tab = 'list'" :class="{ active: tab === 'list' }">
-                    学生管理
+                    {{$t('stuAccount.stuMgt')}}
                 </span>
                 <span class="pane" @click="tab = 'class'" :class="{ active: tab === 'class' }">
-                    班级管理
+                    {{$t('stuAccount.adminClass')}}
                 </span>
                 <span class="pane" @click="tab = 'stulist'" :class="{ active: tab === 'stulist' }">
-                    {{$t('cusMgt.stuListMgt')}}
+                    {{$t('stuAccount.teachClass')}}
                 </span>
-                <!-- <span @click="goMgtStuList" :class="courseListShow.length == 0 ? 'action-btn-disabled action-btn':'action-btn'">
-                    <Icon type="ios-people" size="16" />
-                    <span>{{$t('cusMgt.stuListMgt')}}</span>
-                </span> -->
             </div>
         </div>
         <!-- 学生账号管理 -->

+ 5 - 5
TEAMModelOS/ClientApp/src/view/student-web/App.vue

@@ -45,22 +45,22 @@
                 <!-- <span class="dropdown"> -->
                 <MenuItem name="6" @click.native="noData" title="通知">
                     <span class="info-badge" v-if="MyNo != 6"></span>
-                    <svg-icon icon-class="bell" class="tabIcon1" />
+                    <svg-icon icon-class="bell" class="tabIcon1" title="通知" />
                 </MenuItem>
                 <!-- </span> -->
                 <!-- hiteach课堂记录 -->
                 <MenuItem name="5" @click.native="noData" title="hiteach">
-                    <svg-icon icon-class="hiteach" class="tabIcon4" />
+                    <svg-icon icon-class="hiteach" class="tabIcon4" title="hiteach" />
                 </MenuItem>
                 <!-- 自主学习 -->
                 <MenuItem name="3" @click.native="noData" title="自主学习">
-                    <svg-icon icon-class="note" class="tabIcon1" />
+                    <svg-icon icon-class="note" class="tabIcon1" title="自主学习" />
                 </MenuItem>
                 <MenuItem name="4" to="/studentWeb/eventView" title="活动">
-                    <svg-icon icon-class="selflearning" class="tabIcon2" />
+                    <svg-icon icon-class="selflearning" class="tabIcon2" title="活动" />
                 </MenuItem>
                 <MenuItem name="1" to="/studentWeb/homeView" title="首页">
-                    <svg-icon icon-class="home" class="tabIcon3" />
+                    <svg-icon icon-class="home" class="tabIcon3" title="首页" />
                 </MenuItem>
                 <!-- 加入课程 -->
                 <button class="addcoursebtn"

+ 1 - 1
TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.less

@@ -15,7 +15,7 @@
 		display: flex;
 		align-items: center;
 		padding-left: 15px;
-		z-index: 999;
+		z-index: 10;
 		
 		.subject-select{
 			&-item{

+ 14 - 5
TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.vue

@@ -102,7 +102,7 @@
 							<img src="../../assets/source/zip.png" v-else-if="item.type === 'res'" />
 							<img src="../../assets/source/image.png" v-else-if="item.type === 'thum'" />
 							<img src="../../assets/source/unknow.png" v-else="item.type === 'other'" />
-							<span v-html="item.title"></span>
+							<span v-html="getSimpleText(item.title)" style="max-width: 70%;"></span>
 							<div class="node-resource-tools">
 								<div class="node-resource-tool" @click="onPreview(item)">
 									<Icon type="md-eye" />
@@ -197,8 +197,8 @@
 			<div class="modal-header" slot="header">
 				选择{{ isSchool ? '共编' : '分享' }}教师
 			</div>
-			<InviteTeacher :node="curShareNode"></InviteTeacher>
-			<Button slot="footer" @click="onRelateContent" style="margin-bottom: 20px;" class="modal-btn">确认</Button>
+			<InviteTeacher :node="curShareNode" ref="inviteRef"></InviteTeacher>
+			<Button slot="footer" @click="doInviteTeacher" style="margin-bottom: 20px;" class="modal-btn">确认</Button>
 		</Modal>
 
 		<!-- 预览试题试卷弹窗 -->
@@ -343,6 +343,11 @@
 					}
 				});
 			},
+			/* 提取富文本内容中的文本 */
+			getSimpleText(html) {
+				html = html || '';
+				    return html.replace(/<[^>]+>/g, "");//去掉所有的html标记
+			},
 			/* 切换学段的操作 */
 			onPeriodChange(val) {
 				this.subjectList = this.periodList[val].subjects;
@@ -460,8 +465,8 @@
 				this.curNode.rnodes = []
 				this.curNode.id = ''
 				this.$api.syllabus.GetTreeByVolume({
-					id: volume.id,
-					code: volume.code.replace('Volume-', ''),
+					code: volume.id,
+					// code: volume.code.replace('Volume-', ''),
 					scope: volume.scope
 				}).then(res => {
 					if (!res.error) {
@@ -520,6 +525,10 @@
 				this.curShareNode = data
 				this.isInviteModal = true
 			},
+			/* 点击确认进行课纲的共编或者分享功能 */
+			doInviteTeacher(){
+				let selectedTeacher = this.$refs.inviteRef.teacherList
+			},
 			/* 添加超链接 */
 			onAddLink() {
 				this.$refs.treeRef.curNode.rnodes.push({

+ 103 - 47
TEAMModelOS/ClientApp/src/view/teachcontent/ResBelong.vue

@@ -1,18 +1,23 @@
 <template>
-    <div class="pd-select-wrap">
-        <Dropdown class="sort-dropdown" trigger="click" placement="bottom-start" @on-click="function(e){ filterPeriod = e }" @on-visible-change="dropdownStates" v-if="$store.state.user.schoolProfile.school_base">
-            <span style="cursor: pointer;">
-                <span v-show="showLabel">{{$t('teachContent.uploadTo')}}</span>
-                <b class="title">{{ filterPeriodName }}</b>
-                <Icon type="ios-arrow-down" style="margin-left:8px;"></Icon>
-            </span>
-            <DropdownMenu slot="list" v-for="(item,index) in periods" :value="item.id" :key="index">
-                <DropdownItem :name="item.id">{{ item.name }}</DropdownItem>
-            </DropdownMenu>
-            <DropdownMenu slot="list">
-                <DropdownItem name="public">{{$t('teachContent.public')}}</DropdownItem>
-            </DropdownMenu>
-        </Dropdown>
+    <div class="apply-select-wrap dark-iview-select">
+        <div class="apply-item">
+            <span v-show="showLabel">{{$t('teachContent.applyPd')}}</span>
+            <Select v-model="filterPeriod" multiple style="width:200px" @on-change="pdChange" :max-tag-count="2">
+                <Option v-for="item in periods" :value="item.id" :key="item.id">{{ item.name }}</Option>
+            </Select>
+        </div>
+        <div class="apply-item">
+            <span v-show="showLabel">{{$t('teachContent.applySub')}}</span>
+            <Select v-model="filterSubject" multiple style="width:200px" @on-change="tagChange" :max-tag-count="2">
+                <Option v-for="item in subjects" :value="item.id" :key="item.id">{{ item.name }}</Option>
+            </Select>
+        </div>
+        <div class="apply-item" style="margin-right:0px">
+            <span v-show="showLabel">{{$t('teachContent.applyGrade')}}</span>
+            <Select v-model="filterGrade" multiple style="width:200px" @on-change="tagChange" :max-tag-count="2">
+                <Option v-for="(item,index) in grades" :value="index" :key="index">{{ item }}</Option>
+            </Select>
+        </div>
     </div>
 </template>
 
@@ -21,27 +26,37 @@ import { mapGetters } from 'vuex'
 export default {
     name: 'BasePdSelect',
     props: {
-        pdId:{
-            type:String,
-            default:''
+        pdId: {
+            type: String,
+            default: ''
         },
-        showLabel:{
-            type:Boolean,
-            default:false
+        showLabel: {
+            type: Boolean,
+            default: false
+        },
+        onlyPd: {
+            type: Boolean,
+            default: true
         }
     },
     data() {
         return {
-            filterPeriod: '',
+            filterGrade: [],
+            filterPeriod: [],
+            filterSubject: [],
+            schoolBase: {
+                period: []
+            }
         }
     },
     created() {
         this.$store.dispatch('user/getSchoolProfile').then(
             (res) => {
                 if (res) {
+                    this.schoolBase = res.school_base
                     if (this.periods && !this.pdId) {
                         this.filterPeriod = this.periods[0].id
-                    }else{
+                    } else {
                         this.filterPeriod = this.pdId
                     }
                 }
@@ -52,50 +67,76 @@ export default {
         )
     },
     methods: {
-        dropdownStates(flag) {
-            // if (!flag) this.filterByPeriod()
+        pdChange(data) {
+            //处理学段单选 (如果学段多选,学科和年级不知道对应的是哪个学段)
+            if (data.length) {
+                this.filterPeriod = [data[data.length - 1]]
+            }else{
+                this.filterPeriod = []
+            }
+            this.$emit('tag-change', {
+                period: this.filterPeriod,
+                grades: this.filterGrade,
+                subjects: this.filterSubject
+            })
+        },
+        tagChange() {
+            this.$emit('tag-change', {
+                period: this.filterPeriod,
+                grades: this.filterGrade,
+                subjects: this.filterSubject
+            })
         }
     },
     computed: {
         ...mapGetters({
             periods: 'user/getPeriods', // 學制s
         }),
-        filterPeriodName(){
-            let data = this.periods
-            let pId = this.filterPeriod
-            let name = ''
-            if (pId !== '') {
-                let temp = data.find(item => {
-                    return pId == item.id
+        subjects() {
+            if (this.schoolBase.period && this.filterPeriod) {
+                let pdData = this.schoolBase.period.find(item => {
+                    return item.id == this.filterPeriod
                 })
-                if (temp) {
-                    name = temp.name
-                }else{
-                    name = this.$t('teachContent.public')
+                if (pdData) {
+                    return pdData.subjects
+                } else {
+                    return []
                 }
+            } else {
+                return []
             }
-            return name
         },
+        grades() {
+            if (this.schoolBase.period && this.filterPeriod) {
+                let pdData = this.schoolBase.period.find(item => {
+                    return item.id == this.filterPeriod
+                })
+                if (pdData) {
+                    return pdData.grades
+                } else {
+                    return []
+                }
+            } else {
+                return []
+            }
+        }
     },
     watch: {
-        filterPeriod() {
-            this.$emit('pd-change', this.filterPeriod)
-        },
-        pdId:{
-            handler(){
-                this.filterPeriod = this.pdId
-            }, 
-            immediate:true
+        pdId: {
+            handler() {
+                this.filterPeriod = [this.pdId]
+            },
+            immediate: true
         }
     }
 }
 </script>
-<style lang="less">
-.pd-select-wrap {
-    display: inline-block;
+<style scope lang="less">
+.apply-select-wrap {
     color: #a5a5a5;
 }
 .sort-dropdown {
+    margin-right: 30px;
     .title {
         color: white;
         font-size: 14px;
@@ -115,4 +156,19 @@ export default {
         }
     }
 }
+.apply-item {
+    margin-bottom: 6px;
+    display: inline-block;
+    margin-right: 15px;
+}
 </style>
+<style lang="less">
+.apply-item .ivu-tag {
+    background: #1fb06d;
+    border-color: #1fb06d;
+}
+.apply-item .ivu-tag-text,
+.apply-item .ivu-tag .ivu-icon-ios-close {
+    color: white;
+}
+</style>

+ 17 - 2
TEAMModelOS/ClientApp/src/view/teachcontent/index.less

@@ -516,7 +516,22 @@
 }
 .content-filter-wrap{
     position: absolute;
-    left: 120px;
+    left: 180px;
     display: flex;
-    margin-top: 12px;
+    top: 12px;
+}
+.table-file-name{
+    text-overflow:ellipsis; 
+    overflow:hidden; 
+    white-space:nowrap; 
+    width: ~"calc(100% - 30px)";
+    display: inline-block;
+    vertical-align: top;
+}
+.text-ellipsis{
+    text-overflow:ellipsis; 
+    overflow:hidden; 
+    white-space:nowrap; 
+    width: 100%;
+    display: inline-block;
 }

+ 239 - 31
TEAMModelOS/ClientApp/src/view/teachcontent/index.vue

@@ -81,8 +81,17 @@
             <div class="content-file-list-box">
                 <!--筛选、操作域-->
                 <div class="content-file-filter">
-                    <ResBelong class="pd-filter-wrap" v-show="routerScope == 'school'" @pd-change="(data)=>{filterPeriod = data}"></ResBelong>
-                    <div class="content-filter-wrap">
+                    <!-- 学段筛选条件 -->
+                    <Dropdown class="sort-dropdown" trigger="click" placement="bottom-start" @on-click="function(e){ filterPeriod = e }" @on-visible-change="dropdownStates" v-if="schoolBase && schoolBase.period && routerScope == 'school'">
+                        <span style="cursor: pointer;">
+                            <b class="title">{{ filterPeriodName }}</b>
+                            <Icon type="ios-arrow-down" style="margin-left:8px;"></Icon>
+                        </span>
+                        <DropdownMenu slot="list" v-for="(item,index) in schoolBase.period" :value="item.id" :key="index">
+                            <DropdownItem :name="item.id">{{ item.name }}</DropdownItem>
+                        </DropdownMenu>
+                    </Dropdown>
+                    <div class="content-filter-wrap" :style="{left: routerScope == 'school' ? '180px':'30px'}">
                         <Input v-model="keyWord" search size="small" :placeholder="$t('teachContent.searchText')" class="key-word-search" @on-change="searchKeyWord" @on-search="searchKeyWord" />
                         <CheckboxGroup v-model="extFilter" @on-change="filterFileByExtension">
                             <Checkbox :label="item" v-for="(item ,index) in extensions" :key="index">
@@ -119,7 +128,20 @@
                                     {{formatDate(row.createTime)}}
                                 </div>
                             </template>
+                            <!-- 适用学科 -->
+                            <template slot-scope="{ row, index }" slot="subject">
+                                <span class="text-ellipsis">
+                                    {{getSubjects(row.subjectId)}}
+                                </span>
+                            </template>
+                            <!-- 适用年级 -->
+                            <template slot-scope="{ row, index }" slot="grade">
+                                <span class="text-ellipsis">
+                                    {{getGrades(row.gradeId)}}
+                                </span>
+                            </template>
                             <template slot-scope="{ row, index }" slot="name">
+                                <!-- 文件图标 -->
                                 <div class="dark-iview-input disabled-iview-input teach-file-name">
                                     <div class="file-icon">
                                         <img v-if="row.extension == 'PPT' || row.extension == 'PPTX'" src="../../assets/icon/ppt50.png" width="15" />
@@ -132,7 +154,7 @@
                                         <img v-else-if="row.type == 'res'" src="../../assets/icon/htex.png" width="15" />
                                         <img v-else src="../../assets/icon/prelearn50.png" width="15" />
                                     </div>
-                                    <span v-show="editIndex !== index">{{row.name}}</span>
+                                    <span class="table-file-name" v-show="editIndex !== index">{{row.name}}</span>
                                     <Input v-model="fileListShow[index].name" v-show="editIndex == index" style="width: 300px;" @on-change="checkName" />
                                     <span style="color:#ed4014" v-show="editIndex == index && formatErr">{{$t('teachContent.specialChart')}}(?*:"<>\/|)</span>
                                     <Icon type="md-checkmark" v-show="editIndex == index && !formatErr" @click="confirmRename" class="rename-action-icon" />
@@ -206,6 +228,9 @@ export default {
     },
     data() {
         return {
+            schoolBase: {
+                period: []
+            },
             filterPeriod: '',
             formatErr: false,
             sizeLoading: false,
@@ -257,6 +282,50 @@ export default {
         }
     },
     methods: {
+        //根据学科id换取名称
+        getSubjects(ids) {
+            if (this.schoolBase && this.schoolBase.period && this.filterPeriod && ids) {
+                let pdDada = this.schoolBase.period.find(item => {
+                    return item.id == this.filterPeriod
+                })
+                if (pdDada) {
+                    let subjects = pdDada.subjects.filter(item => {
+                        return ids.includes(item.id)
+                    })
+                    return subjects.map(item => {
+                        return item.name
+                    }).join(',')
+                } else {
+                    return ''
+                }
+            } else {
+                return ''
+            }
+        },
+        // 根据年级index换取名称
+        getGrades(ids) {
+            if (this.schoolBase && this.schoolBase.period && this.filterPeriod && ids) {
+                let pdDada = this.schoolBase.period.find(item => {
+                    return item.id == this.filterPeriod
+                })
+                if (pdDada) {
+                    let grades = []
+                    ids.forEach(item => {
+                        if (pdDada.grades[item]) {
+                            grades.push(pdDada.grades[item])
+                        }
+                    })
+                    return grades.join(',')
+                } else {
+                    return ''
+                }
+            } else {
+                return ''
+            }
+        },
+        dropdownStates(status) {
+
+        },
         //检查文件特殊字符
         checkName(data) {
             let reg = new RegExp('[?*:"<>\/|]')
@@ -482,13 +551,14 @@ export default {
                     title: this.$t('teachContent.tableC1'),
                     slot: 'name',
                     key: 'name',
-                    sortable: true
+                    sortable: true,
+                    minWidth: 180
                 },
                 {
                     title: this.$t('teachContent.tableC4'),
                     slot: 'size',
                     key: 'size',
-                    width: 120,
+                    width: 110,
                     align: 'center',
                     sortable: true
                 },
@@ -496,17 +566,46 @@ export default {
                     title: this.$t('teachContent.tableC6'),
                     slot: 'createTime',
                     key: 'createTime',
-                    width: 150,
+                    width: 120,
                     sortable: true,
                     align: 'center'
                 },
                 {
                     title: this.$t('teachContent.tableC2'),
                     slot: 'action',
-                    width: 160,
+                    width: 150,
                     align: 'center'
                 }
             ]
+            if (this.routerScope == 'school') {
+                // 获取当前学科做筛选条件
+                let subFilters = []
+                let gradeFilters = []
+
+                // 获取当前年级做筛选条件
+
+                let arr = [
+                    {
+                        title: '适用学科',
+                        slot: 'subject',
+                        width: 150,
+                        filters: subFilters,
+                        filterMethod: (value, row) => {
+                            return !row.subjectId || !row.subjectId.length || row.subjectId.includes(value)
+                        }
+                    },
+                    {
+                        title: '适用年级',
+                        slot: 'grade',
+                        width: 150,
+                        filters: gradeFilters,
+                        filterMethod: (value, row) => {
+                            return !row.gradeId || !row.gradeId.length || row.gradeId.includes(value)
+                        }
+                    }
+                ]
+                this.fileColumns.splice(2, 0, ...arr)
+            }
             this.contentTypeList = [
                 {
                     label: '最近',
@@ -867,41 +966,76 @@ export default {
         findFileList() {
             if (this.containerClient) {
                 this.isLoading = true
-                let option = {
-                    //maxPageSize: 290
-                }
-                if (this.mk[this.activeType]) {
-                    option.continuationToken = this.mk[this.activeType]
+                let rd = {
+                    "name": this.routerScope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
+                    "type": this.activeType,
+                    "scope": this.routerScope,
+                    "periodId": this.filterPeriod
                 }
-                let prefix = this.activeType
-                this.containerClient.listBlob({ prefix }, option).then(
-                    (res) => {
-                        this.mk[this.activeType] = res.continuationToken
-                        //拼接授权字符串
-                        for (let i in res.blobList) {
-                            res.blobList[i].url = res.blobList[i].url + this.sasString
-                            if (res.blobList[i].type == 'image') {
-                                res.blobList[i].thum = res.blobList[i].url.replace('/image/', '/thum/')
-                            } else if (res.blobList[i].type == 'video') {
-                                let n = res.blobList[i].blob
+                this.$api.blob.listBlobInfo(rd, this.urlString, this.containerName).then(
+                    res => {
+                        console.log('转化之后的数据格式:', res)
+                        for (let i in res) {
+                            res[i].url = res[i].url + this.sasString
+                            if (res[i].type == 'image') {
+                                res[i].thum = res[i].url.replace('/image/', '/thum/')
+                            } else if (res[i].type == 'video') {
+                                let n = res[i].blob
                                 n = n.replace('/video/', '/thum/')
-                                n = n.replace(res.blobList[i].name, res.blobList[i].name.slice(0, res.blobList[i].name.lastIndexOf('.'))) + '.png'
-                                res.blobList[i]['thum'] = res.blobList[i].url.replace(res.blobList[i].blob, n)
+                                n = n.replace(res[i].name, res[i].name.slice(0, res[i].name.lastIndexOf('.'))) + '.png'
+                                res[i]['thum'] = res[i].url.replace(res[i].blob, n)
                             }
                         }
-                        this.fileList[this.activeType] = res.blobList
+                        this.fileList[this.activeType] = res
                         this.fileListShow = this._.cloneDeep(this.fileList[this.activeType])
                         this.searchBefore = this.fileList[this.activeType]
                         this.getFilesExtension()
                     },
-                    (err) => {
-
+                    err => {
+                        console.log('error')
                     }
                 ).finally(() => {
                     setTimeout(() => {
                         this.isLoading = false
                     }, 500)
                 })
+
+                //原来由前端直接listblob的逻辑
+                // let option = {
+                //     //maxPageSize: 290
+                // }
+                // if (this.mk[this.activeType]) {
+                //     option.continuationToken = this.mk[this.activeType]
+                // }
+                // let prefix = this.activeType
+                // this.containerClient.listBlob({ prefix }, option).then(
+                //     (res) => {
+                //         this.mk[this.activeType] = res.continuationToken
+                //         //拼接授权字符串
+                //         for (let i in res.blobList) {
+                //             res.blobList[i].url = res.blobList[i].url + this.sasString
+                //             if (res.blobList[i].type == 'image') {
+                //                 res.blobList[i].thum = res.blobList[i].url.replace('/image/', '/thum/')
+                //             } else if (res.blobList[i].type == 'video') {
+                //                 let n = res.blobList[i].blob
+                //                 n = n.replace('/video/', '/thum/')
+                //                 n = n.replace(res.blobList[i].name, res.blobList[i].name.slice(0, res.blobList[i].name.lastIndexOf('.'))) + '.png'
+                //                 res.blobList[i]['thum'] = res.blobList[i].url.replace(res.blobList[i].blob, n)
+                //             }
+                //         }
+                //         this.fileList[this.activeType] = res.blobList
+                //         this.fileListShow = this._.cloneDeep(this.fileList[this.activeType])
+                //         this.searchBefore = this.fileList[this.activeType]
+                //         this.getFilesExtension()
+                //     },
+                //     (err) => {
+
+                //     }
+                // ).finally(() => {
+                //     setTimeout(() => {
+                //         this.isLoading = false
+                //     }, 500)
+                // })
             }
         },
 
@@ -981,14 +1115,41 @@ export default {
                 this.extensions.push(ext.toUpperCase())
             }
             this.extensions = [...new Set(this.extensions)]
+        },
+        //根据学段筛选资源
+        filterByPeriod() {
+            // let files = this.fileList[this.activeType] || []
+            // this.fileListShow = files.filter(item => {
+            //     return !item.periodId || !item.periodId.length || item.periodId.includes(this.filterPeriod)
+            // })
+            this.fileList = {}
+            this.findFileList()
         }
+
+    },
+    computed: {
+        filterPeriodName() {
+            if (this.schoolBase && this.schoolBase.period) {
+                let data = this.schoolBase.period
+                let pId = this.filterPeriod
+                let name = ''
+                if (pId !== '') {
+                    let temp = data.filter(item => {
+                        return pId == item.id
+                    })
+                    if (temp.length > 0) name = temp[0].name
+                }
+                return name
+            } else {
+                return ''
+            }
+
+        },
     },
     mounted() {
         let box = document.getElementById('card-box')
         this.waterfallWidth = box.clientWidth - 60
-        Date.prototype.toLocaleString = function () {
-            return this.getFullYear() + '/' + (this.getMonth() + 1) + '/' + this.getDate()
-        }
+
         //处理瀑布流组件宽度
         this.erd = elementResizeDetectorMaker()
         this.erd.listenTo(document.getElementById("card-box"), () => {
@@ -1003,6 +1164,20 @@ export default {
         })
     },
     created() {
+        this.$store.dispatch('user/getSchoolProfile').then(
+            (res) => {
+                if (res) {
+                    this.schoolBase = res.school_base
+                    if (this.schoolBase.period.length) this.filterPeriod = this.schoolBase.period[0].id
+                }
+            },
+            (err) => {
+                this.$Message.error('API error!')
+            }
+        )
+        Date.prototype.toLocaleString = function () {
+            return this.getFullYear() + '/' + (this.getMonth() + 1) + '/' + this.getDate()
+        }
         this.initData()
         let cont = ''
         if (this.$route.name == 'schoolcontent') {
@@ -1040,12 +1215,45 @@ export default {
                 this.getSasStr()
             },
             immediate: true
+        },
+        filterPeriod: {
+            handler(n, o) {
+                this.filterByPeriod()
+                // 获取当前学科做筛选条件
+                let subFilters = []
+                let gradeFilters = []
+                if (this.schoolBase && this.schoolBase.period && this.filterPeriod) {
+                    let pdData = this.schoolBase.period.find(item => {
+                        return this.filterPeriod == item.id
+                    })
+                    if (pdData) {
+                        subFilters = pdData.subjects.map(item => {
+                            return {
+                                label: item.name,
+                                value: item.id
+                            }
+                        })
+                        gradeFilters = pdData.grades.map((item, index) => {
+                            return {
+                                label: item,
+                                value: index + ''
+                            }
+                        })
+                    }
+                }
+                this.fileColumns[2].filters = subFilters
+                this.fileColumns[3].filters = gradeFilters
+            }
         }
     }
 }
 </script>
 <style scoped lang="less">
 @import "./index.less";
+.sort-dropdown {
+    margin-left: 15px;
+    padding-top: 15px;
+}
 </style>
 <style>
 .content-file-filter .ivu-input {

+ 1 - 1
TEAMModelOS/ClientApp/src/view/vote/ManageVote.less

@@ -148,7 +148,7 @@
 
     .hw-info-box {
         width: 100%;
-		background-color: #2b2b2e;
+		background-color: #242328;
         border-right: 1px solid @borderColor;
     }
 

+ 21 - 8
TEAMModelOS/Controllers/Core/BlobController.cs

@@ -530,9 +530,9 @@ namespace TEAMModelOS.Controllers.Core
                 request.TryGetProperty("name", out JsonElement name);
                 request.TryGetProperty("type", out JsonElement type);
                 request.TryGetProperty("scope", out JsonElement scope);
-                request.TryGetProperty("period", out JsonElement period);
+                request.TryGetProperty("periodId", out JsonElement periodId);
                 var client = _azureCosmos.GetCosmosClient();
-                var queryslt = $"SELECT  value(c) FROM c WHERE c.type='{type}' and  c.period='{period}'";
+                var queryslt = $"SELECT  value(c) FROM c join A1 in  c.periodId  WHERE c.type='{type}' and  A1 in ('{periodId}')";
                 if (scope.GetString().Equals("school"))
                 {
                     await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Bloblog>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Bloblog-{name}") }))
@@ -557,7 +557,7 @@ namespace TEAMModelOS.Controllers.Core
         /*
          新增 编辑接口
         {
-            "period": "",
+            "periodId": "",
             "scope": "school",
             "name": "hbcn",
             "url": "video/xxx.png",
@@ -577,12 +577,14 @@ namespace TEAMModelOS.Controllers.Core
         /// </summary>
         /// <param name="request"></param>
         /// <returns></returns>
-        [HttpPost("bloblog-upsert")]
-        public async Task<ActionResult> BloblogUpsert(JsonElement request) {
+        [HttpPost("bloblog-opt")]
+        public async Task<ActionResult> BloblogOpt(JsonElement request) {
 
             try
             {
-                request.TryGetProperty("period", out JsonElement period);
+                request.TryGetProperty("periodId", out JsonElement periodId);
+                request.TryGetProperty("subjectId", out JsonElement subjectId);
+                request.TryGetProperty("gradeId", out JsonElement gradeId);
                 request.TryGetProperty("scope", out JsonElement scope);
                 request.TryGetProperty("name", out JsonElement name);
                 request.TryGetProperty("url", out JsonElement jurl);
@@ -610,7 +612,11 @@ namespace TEAMModelOS.Controllers.Core
                         {
                             await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Bloblog>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Bloblog-{name}") }))
                             {
+                                item.time = now;
                                 item.size = size != null && size.HasValue ? size.Value : 0;
+                                item.periodId = periodId.ValueKind.Equals(JsonValueKind.Array) ? periodId.ToObject<List<string>>() : new List<string> { "" };
+                                item.subjectId = subjectId.ValueKind.Equals(JsonValueKind.Array) ? subjectId.ToObject<List<string>>() : new List<string> { "" };
+                                item.gradeId = gradeId.ValueKind.Equals(JsonValueKind.Array) ? gradeId.ToObject<List<string>>() : new List<string> { "" };
                                 await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Bloblog>(item, item.id, new Azure.Cosmos.PartitionKey(item.code));
                                 exsit = true;
                             }
@@ -618,12 +624,17 @@ namespace TEAMModelOS.Controllers.Core
                         else if (scope.GetString().Equals("teacher")) {
                             await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Bloblog>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Bloblog-{name}") }))
                             {
+                                item.time = now;
                                 item.size = size != null && size.HasValue ? size.Value : 0;
+                                item.periodId = periodId.ValueKind.Equals(JsonValueKind.Array) ? periodId.ToObject<List<string>>() : new List<string> { "" };
+                                item.subjectId = subjectId.ValueKind.Equals(JsonValueKind.Array) ? subjectId.ToObject<List<string>>() : new List<string> { "" };
+                                item.gradeId = gradeId.ValueKind.Equals(JsonValueKind.Array) ? gradeId.ToObject<List<string>>() : new List<string> { "" };
                                 await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Bloblog>(item, item.id, new Azure.Cosmos.PartitionKey(item.code));
                                 exsit = true;
                             }
                         }
                     } catch (Exception ex) {
+                        await _dingDing.SendBotMsg($"IES5,{_option.Location},blob/refresh-blob()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
                     }
                     if (!exsit) {
                         var blob = new Bloblog
@@ -634,7 +645,9 @@ namespace TEAMModelOS.Controllers.Core
                             url = url,
                             time = now,
                             size = size != null && size.HasValue ? size.Value : 0,
-                            period = $"{period}",
+                            periodId = periodId.ValueKind.Equals(JsonValueKind.Array) ? periodId.ToObject<List<string>>() : new List<string> { "" } ,
+                            subjectId= subjectId.ValueKind.Equals(JsonValueKind.Array) ? subjectId.ToObject<List<string>>() : new List<string> { ""},
+                            gradeId = gradeId.ValueKind.Equals(JsonValueKind.Array) ? gradeId.ToObject<List<string>>() : new List<string> { "" },
                             type = u
                         };
                         if (scope.GetString().Equals("school"))
@@ -663,7 +676,7 @@ namespace TEAMModelOS.Controllers.Core
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"IES5,{_option.Location},blon/refresh-blob()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                await _dingDing.SendBotMsg($"IES5,{_option.Location},blob/refresh-blob()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
             }
             return Ok(new { status = 200 });
         }

+ 19 - 2
TEAMModelOS/Controllers/Core/CoreController.cs

@@ -19,7 +19,7 @@ using TEAMModelOS.SDK.PngQuant;
 
 namespace TEAMModelOS.Controllers.Core
 {
-    [Route("Core")]
+    [Route("core")]
     [ApiController]
     public class CoreController : ControllerBase
     {
@@ -33,7 +33,12 @@ namespace TEAMModelOS.Controllers.Core
             _dingDing = dingDing;
             _option = option?.Value;
         }
-
+        [HttpPost("apply-school")]
+        public async Task<IActionResult> ApplySchool(ApplySchool request) {
+            await _dingDing.SendBotMsg($"有新学校申请。\n申请站点:{_option.Location}\n申请学校:{request.name}\n所在国家\\地区:{request.area}\n申请人:{request.tmdname}({request.tmdid})\n联系电话:{request.cellphone}\n备注:{request.content}", GroupNames.AI智慧學校申請通知群);
+            return Ok();
+          
+        }
         [HttpPost("system-info")]
         [RequestSizeLimit(100_000_000)] //最大100m左右
         public  IActionResult  SystemInfo(JsonElement request) {
@@ -150,4 +155,16 @@ namespace TEAMModelOS.Controllers.Core
 
         }
     }
+
+
+    public record ApplySchool { 
+        public string name { get; set; }
+        public string site { get; set; }
+        public string area { get; set; }
+        public string tmdname { get; set; }
+        public string tmdid { get; set; }
+        public string cellphone { get; set; }
+        public string content { get; set; }
+
+    }
 }

+ 182 - 154
TEAMModelOS/Controllers/Syllabus/ShareController.cs

@@ -6,6 +6,7 @@ using Microsoft.Extensions.Options;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelOS.Filter;
@@ -42,15 +43,15 @@ namespace TEAMModelOS.Controllers
          {
             "school": "学校编码",
             "scope":"school|private",
-            "tmdid":"分享给谁,邀请谁的tmdid",
-            "name":"分享给谁,邀请谁的name",
-            "sid":"课纲的id",
-            "scode":"课纲册别的分区键",
-            "sname":"课纲分享节点的名称",
+            "tmdInfo":["tmdid":"id1","tmdname":"name1"],
             "coedit":true,
             "share":true,
             "issuer":"权限颁发者tmdid",
-            "snodes":["分享的节点 all 或者節點id"]
+            "opt":"add/del/edit"
+            "syllabusId":"分享的课纲章节id",
+            "syllabusName":"章节名称",
+            "volumeId":"册别id",
+            "volumeName":"册别name"
         }
          */
 
@@ -70,42 +71,67 @@ namespace TEAMModelOS.Controllers
                 //需要判断id== req.issuer  才能进行授权操作
                 if (request.scope.Equals("school"))
                 {
-                    Volume volume = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Volume>(request.sid, new PartitionKey(request.scode));
+                    Syllabus syllabusD = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
                     if (request.opt == "del")
                     {
-                        if (volume.auth.IsNotEmpty())
+                        if (syllabusD.auth.IsNotEmpty())
                         {
-                            var del = volume.auth.Where(x => x.tmdid == request.tmdid).FirstOrDefault();
-                            volume.auth.Remove(del);
-                            await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Volume>(volume, request.sid, new PartitionKey(request.scode));
-                            await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.sid, new PartitionKey($"Share-{request.tmdid}"));
+                            List<SyllabusAuth> syllabusAuths = new List<SyllabusAuth>();
+                            syllabusD.auth.ForEach(x=> {
+                                if (request.tmdInfo.Select(tmd=>tmd.tmdid).Contains(x.tmdid)) {
+                                    syllabusAuths.Add(x);
+                                }   
+                            }) ;
+                            syllabusAuths.ForEach(x => {
+                                syllabusD.auth.Remove(x);
+                            });
+                            await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabusD, request.volumeId, new PartitionKey($"Syllabus-{request.volumeId}"));
+                            request.tmdInfo.ForEach(async x => {
+                                await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{x.tmdid}"));
+                            });
+                            
                         }
                     }
                     else if (request.opt.Equals("add") || request.opt.Equals("edit"))
                     {
-                        (Volume vlm, Share share) = DoAuth(request, volume);
-                        await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Share>(share, new PartitionKey($"Share-{request.tmdid}"));
-                        await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<Volume>(volume, new PartitionKey(request.scode));
+                        (Syllabus syllabus, List<Share> shares) = DoAuth(request, syllabusD);
+                        shares.ForEach(async x=> {
+                            await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Share>(x, new PartitionKey($"Share-{x.code}"));
+                        });
+                       
+                        await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<Syllabus>(syllabus, new PartitionKey($"Syllabus-{request.volumeId}"));
                     }
                 }
                 else if (request.scope.Equals("private"))
                 {
-                    Volume volume = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Volume>(request.sid, new PartitionKey(request.scode));
+                    Syllabus syllabusD = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
                     if (request.opt == "del")
                     {
-                        if (volume.auth.IsNotEmpty())
+                        if (syllabusD.auth.IsNotEmpty())
                         {
-                            var del = volume.auth.Where(x => x.tmdid == request.tmdid).FirstOrDefault();
-                            volume.auth.Remove(del);
-                            await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Volume>(volume, request.sid, new PartitionKey(request.scode));
-                            await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.sid, new PartitionKey($"Share-{request.tmdid}"));
+                            List<SyllabusAuth> syllabusAuths = new List<SyllabusAuth>();
+                            syllabusD.auth.ForEach(x => {
+                                if (request.tmdInfo.Select(tmd=>x.tmdid).Contains(x.tmdid))
+                                {
+                                    syllabusAuths.Add(x);
+                                }
+                            });
+                            syllabusAuths.ForEach(x => {
+                                syllabusD.auth.Remove(x);
+                            });
+                            await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Syllabus>(syllabusD, request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
+                            request.tmdInfo.ForEach(async x => {
+                                await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{x.tmdid}"));
+                            });
                         }
                     }
                     else if (request.opt.Equals("add") || request.opt.Equals("edit"))
                     {
-                        (Volume vlm, Share share) = DoAuth(request, volume);
-                        await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Share>(share, new PartitionKey($"Share-{request.tmdid}"));
-                        await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Volume>(volume, new PartitionKey(request.scode));
+                        (Syllabus vlm, List<Share> shares) = DoAuth(request, syllabusD);
+                        shares.ForEach(async x => {
+                            await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Share>(x, new PartitionKey($"Share-{x.code}"));
+                        });
+                        await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Syllabus>(syllabusD, new PartitionKey($"Syllabus-{request.volumeId}"));
                     }
                 }
                 return Ok(new { code=200});
@@ -116,77 +142,89 @@ namespace TEAMModelOS.Controllers
             return Ok(new { code = 500 });
         }
 
-        private (Volume,Share) DoAuth(ShareData request,Volume volume) {
+        private (Syllabus, List<Share>) DoAuth(ShareData request, Syllabus syllabus)
+        {
             long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-            var share = new Share
-            {
-                id = request.sid,
-                code = $"Share-{request.tmdid}",
-                pk = "Share",
-                ttl = -1,
-                scode = request.scode,
-                issuer = request.issuer,
-                createTime = now,
-                school = request.school,
-                scope = request.scope,
-                coedit=request.coedit,
-                share=request.share,
-                sname=request.sname
-            };
-            if (volume.auth.IsNotEmpty())
-            {
-                bool flag = false;
-                int indx = 0;
-                for (int index = 0; index < volume.auth.Count; index++)
+            List<Share> shares = new List<Share>();
+            request.tmdInfo.ForEach(xmd => {
+                var share = new Share
                 {
-                    if (volume.auth[index].tmdid == request.tmdid)
+                    id = request.syllabusId,
+                    volumeId = request.volumeId,
+                    volumeName = request.volumeName,
+                    syllabusName = request.syllabusName,
+                    code = $"Share-{xmd.tmdid}",
+                    pk = "Share",
+                    ttl = -1,
+                    issuer = request.issuer,
+                    createTime = now,
+                    school = request.school,
+                    scope = request.scope,
+                    coedit = request.coedit,
+                    share = request.share
+                };
+                shares.Add(share);
+            });
+            
+            if (syllabus.auth.IsNotEmpty())
+            {
+                request.tmdInfo.ForEach(xmd => {
+
+                    bool flag = false;
+                    int indx = 0;
+                    for (int index = 0; index < syllabus.auth.Count; index++)
                     {
-                        flag = true;
-                        indx = index;
-                        break;
+                        if (syllabus.auth[index].tmdid == xmd.tmdid)
+                        {
+                            flag = true;
+                            indx = index;
+                            break;
+                        }
                     }
-                }
-                ///更新位置上的授权信息
-                if (flag)
-                {
-                    volume.auth[indx] = new SyllabusAuth
+                    ///更新位置上的授权信息
+                    if (flag)
                     {
-                        tmdid = request.tmdid,
-                        name = request.name,
-                        coedit = request.coedit,
-                        share = request.share,
-                        snodes = request.snodes
-                    };
-                }
-                //新增
-                else
-                {
-                    volume.auth.Add(new SyllabusAuth
+                        syllabus.auth[indx] = new SyllabusAuth
+                        {
+                            tmdid = xmd.tmdid,
+                            tmdname = xmd.tmdname,
+                            coedit = request.coedit,
+                            share = request.share,
+                        };
+                    }
+                    //新增
+                    else
                     {
-                        tmdid = request.tmdid,
-                        name = request.name,
-                        coedit = request.coedit,
-                        share = request.share,
-                        snodes = request.snodes
-                    });
-                }
+                        syllabus.auth.Add(new SyllabusAuth
+                        {
+                            tmdid = xmd.tmdid,
+                            tmdname = xmd.tmdname,
+                            coedit = request.coedit,
+                            share = request.share,
+                        });
+                    }
+                });
             }
             else
             {
-                volume.auth = new List<SyllabusAuth>() {
-                    new SyllabusAuth {
-                        tmdid=request.tmdid,
-                        name=request.name,
-                        coedit=request.coedit,
-                        share=request.share,
-                        snodes=request.snodes
-                    }
-                };
+                request.tmdInfo.ForEach(xmd => {
+                    syllabus.auth = new List<SyllabusAuth>() {
+                        new SyllabusAuth {
+                            tmdid = xmd.tmdid,
+                            tmdname = xmd.tmdname,
+                            coedit=request.coedit,
+                            share=request.share,
+                        }
+                    };
+                });
             }
-            return (volume, share);
+            return (syllabus, shares);
         }
+
+
+
         /// <summary>
-        /// {"code":"教师编码"} 
+        /// {"code":"教师编码","type":"coedit/share"} 
         /// 教师拉取自己收到的分享及共编
         /// </summary>
         /// <param name="request"></param>
@@ -200,14 +238,32 @@ namespace TEAMModelOS.Controllers
             {
                 List<Share> shares = new List<Share>();
                 if (!request.TryGetProperty("code", out JsonElement code)) { return BadRequest(); }
+                if (!request.TryGetProperty("type", out JsonElement type)) { return BadRequest(); }
+                if (!request.TryGetProperty("id", out JsonElement id)) { return BadRequest(); }
                 var client = _azureCosmos.GetCosmosClient();
-
-                await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Share>(queryText: $"select value(c) from c ",
+                StringBuilder queryText = new StringBuilder("select value(c) from c");
+                if (type.ValueKind.Equals(JsonValueKind.String) && type.GetString() == "coedit")
+                {
+                    queryText.Append(" where c.coedit=true");
+                }
+                else if (type.ValueKind.Equals(JsonValueKind.String) && type.GetString() == "share")
+                {
+                    queryText.Append(" where c.share=true");
+                }
+                else {
+                    await _dingDing.SendBotMsg($"OS,{_option.Location},teacher/share/find()\n type== coedit|share 参数必选一个", GroupNames.醍摩豆服務運維群組);
+                    return BadRequest();
+                }
+                if (id.ValueKind.Equals(JsonValueKind.String) && !string.IsNullOrEmpty(id.GetString())) {
+                    queryText.Append($" and c.id='{id}'");
+                }
+                await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Share>(queryText: queryText.ToString(),
                 requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Share-{code}") }))
                 {
                     shares.Add(item);
                 }
-                return Ok(new { shares = shares });
+                var sharesGp  =  shares.GroupBy(x => new {id= x.volumeId ,code=x.scope=="school"?x.school:x.issuer}).Select(y=>new { id=y.Key.id,code=y.Key.code,list=y.ToList()});
+                return Ok(new { shares = sharesGp });
             }
             catch (Exception ex)
             {
@@ -216,14 +272,24 @@ namespace TEAMModelOS.Controllers
             }
 
         }
+
+        public record ShareView
+        {
+            public string scope { get; set; }
+           // public string code { get; set; }
+            public string school { get; set; }
+            public string issuer { get; set; }
+            public string volumeId { get; set; }
+            public List<string> syllabusId { get; set; }
+        }
+
         /*
             {
                 "scope": "school/private",
                 "school": "学校编码",
                 "issuer": "权限颁发者",
-                "id": "分享或共编的id",
-                "code": "分享或共编的分区键",
-                "scode": "分享或共编的scode"
+                "volumeId": "册别id",
+                "syllabusId": ["id1课纲章节节点id","id2课纲章节节点id"],
             }
          */
         /// <summary>
@@ -232,90 +298,51 @@ namespace TEAMModelOS.Controllers
         /// <param name="request"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
-        [HttpPost("view")]
+        [HttpPost("view-share")]
        // [AuthToken(Roles = "Teacher")]
-        public async Task<IActionResult> View(Share request)
+        public async Task<IActionResult> View(ShareView request)
         {
             try
             {
-                //var (id, _, _, school) = HttpContext.GetAuthTokenInfo();
-                //if (!request.code.Equals($"Share-{id}"))
-                //{
-                //    return BadRequest();
-                //}
-                Syllabus syllabus;
+                List<SyllabusTreeNode> treeNodes = new List<SyllabusTreeNode>();
                 Volume volume;
                 var client = _azureCosmos.GetCosmosClient();
                 string code = null;
+                List<string> sid = new List<string>();
+                request.syllabusId.ForEach(x => { sid.Add($"'{x}'"); });
+                var sidSql= string.Join(",", sid);
                 if (request.scope == "school")
                 {
                     code = request.school;
-                    syllabus = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>(request.id, new PartitionKey(request.scode));
-                    volume = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Volume>(request.id, new PartitionKey($"Volume-{code}"));
+                    var queryslt = $"SELECT  value(c) FROM c where c.id in ({sidSql})";
+                    await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.volumeId}") }))
+                    {
+                        List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
+                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth };
+                        treeNodes.Add(tree);
+
+                    }
+                    volume = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Volume>(request.volumeId, new PartitionKey($"Volume-{code}"));
+                    
                 }
                 else if (request.scope == "private")
                 {
                     code = request.issuer;
-                    syllabus = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>(request.id, new PartitionKey(request.scode));
-                    volume = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Volume>(request.id, new PartitionKey($"Volume-{code}"));
+                    var queryslt = $"SELECT  value(c) FROM c where c.id in ({sidSql})";
+                    await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.volumeId}") }))
+                    {
+                        List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
+                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth };
+                        treeNodes.Add(tree);
+                    }
+                    volume = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Volume>(request.volumeId, new PartitionKey($"Volume-{code}"));
                 }
                 else
                 {
                     return BadRequest();
                 }
-                bool coedit = false;
-                bool share = false;
-                SyllabusTreeNode  etree = null;
-                List<string> snodes = null;
-                if (volume.auth.IsNotEmpty()) {
-                    foreach (var x in volume.auth) {
-                        if ($"Share-{x.tmdid }" == request.code)
-                        {
-                            coedit = x.coedit;
-                            share = x.share;
-                            snodes = x.snodes;
-                            break;
-                        }
-                    }
-                }
-                if (coedit)
-                {
-                    var treechd = SyllabusService.ListToTree(syllabus.children);
-                    etree = new SyllabusTreeNode() {
-                        id = syllabus.id,
-                        trees = treechd
-                    };
-                }
-                SyllabusTreeNode stree = new SyllabusTreeNode();
-                if (share && snodes.IsNotEmpty()) {
-                    stree = new SyllabusTreeNode()
-                    {
-                        id = syllabus.id,
-                    };
-                    snodes.ForEach(x => {
-                        SyllabusTree syllabusTree = null;
-                        foreach (var node in syllabus.children) {
-                            if (node.id == x) {
-                                syllabusTree = new SyllabusTree { 
-                                    id=node.id,
-                                    pid=node.pid,
-                                    order=node.order,
-                                    rnodes=node.rnodes,
-                                    cids=node.cids
-                                };
-                                break;
-                            }
-                        }
-                        HashSet<Tnode> newNodes = new HashSet<Tnode>();
-                        SyllabusService.GetNewNode(syllabus.children, x, newNodes);
-                        var trees = SyllabusService.ListToTree(newNodes.ToList());
-                        if (syllabusTree != null) {
-                            syllabusTree.children.AddRange(trees);
-                            stree.trees.Add(syllabusTree);
-                        }
-                    });
-                }
-                return Ok(new { coedit, share, etree,stree });
+                
+                return Ok(new { volume,tree= treeNodes });
             }
             catch (Exception ex) {
                 await _dingDing.SendBotMsg($"OS,{_option.Location},teacher/share/view()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
@@ -337,4 +364,5 @@ namespace TEAMModelOS.Controllers
 
         }
     }
+   
 }

+ 103 - 267
TEAMModelOS/Controllers/Syllabus/SyllabusController.cs

@@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Http;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using Azure.Cosmos;
 using TEAMModelOS.Services.Common;
+using Microsoft.Extensions.Options;
 
 namespace TEAMModelOS.Controllers
 {
@@ -28,163 +29,15 @@ namespace TEAMModelOS.Controllers
     public class SyllabusController : ControllerBase
     {
         private readonly AzureCosmosFactory _azureCosmos;
-
-
-        public SyllabusController(AzureCosmosFactory azureCosmos)
+        private readonly Option _option;
+        private readonly DingDing _dingDing;
+        public SyllabusController(AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option)
         {
             _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _option = option?.Value;
         }
 
-        /*
-        {
-    "id": "0baf00db-0768-4b62-a8f7-280f6bcebf71",
-    "scope": "school",
-    "trees": [
-        {
-            "children": [
-                {
-                    "children": [],
-                    "id": "AC4BA269-541B-4DFC-92A5-D773068A6439",
-                    "pid": "2dfcc62e-8eea-9881-dc79-384b2f0afbec",
-                    "order": 0,
-                    "rnodes": [
-                        {
-                            "type": "doc",
-                            "id": "a2bee388-5584-72cc-1d9a-d8a77d255364",
-                            "code": "hbcn",
-                            "scope": "private",
-                            "cntr": "1595321354",
-                            "link": [
-                                "https://teammodelstorage.blob.core.chinacloudapi.cn/1595321354/doc/2020智慧課堂與智慧教研.pptx"
-                            ],
-                            "title": "2020智慧課堂與智慧教研.pptx"
-                        }
-                    ],
-                    "cids": [],
-                    "creatorId": null,
-                    "updateTime": 0,
-                    "title": "1-1 新冠疫情小贴士"
-                }
-            ],
-            "id": "2dfcc62e-8eea-9881-dc79-384b2f0afbec",
-            "pid": "0baf00db-0768-4b62-a8f7-280f6bcebf71",
-            "order": 0,
-            "rnodes": [
-                {
-                    "type": "doc",
-                    "id": "cf1b4d21-66e1-e6c7-c944-30a03e419fa6",
-                    "code": "hbcn",
-                    "scope": "school",
-                    "cntr": "hbcn",
-                    "link": [
-                        "https://teammodelstorage.blob.core.chinacloudapi.cn/hbcn/syllabus/IES5试卷模板制作说明(终).pdf"
-                    ],
-                    "title": "IES5试卷模板制作说明(终).pdf"
-                },
-                {
-                    "type": "doc",
-                    "id": "f3e82595-7340-a5fe-1004-04538ca09b86",
-                    "code": "hbcn",
-                    "scope": "school",
-                    "cntr": "hbcn",
-                    "link": [
-                        "https://teammodelstorage.blob.core.chinacloudapi.cn/hbcn/syllabus/111.pdf"
-                    ],
-                    "title": "111.pdf"
-                },
-                {
-                    "type": "doc",
-                    "id": "e1b31639-dad9-9efb-020b-159dd045f238",
-                    "code": "hbcn",
-                    "scope": "school",
-                    "cntr": "hbcn",
-                    "link": [
-                        "https://teammodelstorage.blob.core.chinacloudapi.cn/hbcn/doc/6789.pdf"
-                    ],
-                    "title": "6789.pdf"
-                },
-                {
-                    "type": "doc",
-                    "id": "aaeb4b5c-0450-cb4d-a1ac-244f3d115c4a",
-                    "code": "hbcn",
-                    "scope": "private",
-                    "cntr": "1595321354",
-                    "link": [
-                        "https://teammodelstorage.blob.core.chinacloudapi.cn/1595321354/doc/422北京培新活动邀请函.pdf"
-                    ],
-                    "title": "422北京培新活动邀请函.pdf"
-                },
-                {
-                    "type": "doc",
-                    "id": "c5f5838c-5c2f-5e9b-a734-a473cd2cad2e",
-                    "code": "hbcn",
-                    "scope": "school",
-                    "cntr": "hbcn",
-                    "link": [
-                        "https://teammodelstorage.blob.core.chinacloudapi.cn/hbcn/doc/6666.pdf"
-                    ],
-                    "title": "6666.pdf"
-                },
-                {
-                    "type": "doc",
-                    "id": "4a106c8e-6831-5f4b-4ec3-3c18f778cab2",
-                    "code": "hbcn",
-                    "scope": "school",
-                    "cntr": "hbcn",
-                    "link": [
-                        "https://teammodelstorage.blob.core.chinacloudapi.cn/hbcn/doc/6.pdf"
-                    ],
-                    "title": "6.pdf"
-                }
-            ],
-            "cids": [
-                "AC4BA269-541B-4DFC-92A5-D773068A6439"
-            ],
-            "creatorId": null,
-            "updateTime": 0,
-            "title": "第一单元 新冠疫情防控"
-        },
-        {
-            "children": [
-                {
-                    "children": [],
-                    "id": "FC5132E1-9723-4875-B3B5-D3DC98D194FA",
-                    "pid": "4f12752c-852f-6e90-a3df-1f1f710af23d",
-                    "order": 0,
-                    "rnodes": [],
-                    "cids": [],
-                    "creatorId": null,
-                    "updateTime": 0,
-                    "title": "2-1 全球醍摩豆智慧教育研究院"
-                },
-                {
-                    "children": [],
-                    "id": "3CAD52BE-67B6-4EDB-8EFB-9122960D816A",
-                    "pid": "4f12752c-852f-6e90-a3df-1f1f710af23d",
-                    "order": 1,
-                    "rnodes": [],
-                    "cids": [],
-                    "creatorId": null,
-                    "updateTime": 0,
-                    "title": "2-2 醍摩豆研究院课程体系"
-                }
-            ],
-            "id": "4f12752c-852f-6e90-a3df-1f1f710af23d",
-            "pid": "0baf00db-0768-4b62-a8f7-280f6bcebf71",
-            "order": 1,
-            "rnodes": [],
-            "cids": [
-                "FC5132E1-9723-4875-B3B5-D3DC98D194FA",
-                "3CAD52BE-67B6-4EDB-8EFB-9122960D816A"
-            ],
-            "creatorId": null,
-            "updateTime": 0,
-            "title": "第二单元 醍摩豆手册学习"
-        }
-    ]
-}
-              */
-
         /// <summary>
         /// 批量保存或更新课纲
         /// 
@@ -193,38 +46,96 @@ namespace TEAMModelOS.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("upsert-tree")]
-        public async Task<IActionResult> SaveOrUpdateAsTree(SyllabusTreeNode request)
+        public async Task<IActionResult> SaveOrUpdateAsTree(List<SyllabusTreeNode> request)
         {
-            List<List<SyllabusTree>> tts = new List<List<SyllabusTree>>();
-            foreach (var tree in request.trees) {
-                Syllabus syllabus = new Syllabus();
+            foreach (SyllabusTreeNode syllabusTree in request) {
                 List<Tnode> nodes = new List<Tnode>();
-                SyllabusService.TreeToList(new List<SyllabusTree> { tree }, nodes);
-                syllabus.children = nodes;
-                syllabus.id = !string.IsNullOrEmpty(tree.id) ? tree.id : Guid.NewGuid().ToString();
-                syllabus.code = $"Syllabus-{request.id}";
-                syllabus.pk = "Syllabus";
-                syllabus.ttl = -1;
-                syllabus.volumeId = request.id;
-                if (request.scope == "school")
+                SyllabusService.TreeToList(syllabusTree.trees, nodes);
+                if (!string.IsNullOrEmpty(syllabusTree.id))
                 {
-                    await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").UpsertItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{request.id}"));
+                    Syllabus syllabus = null;
+                    if (syllabusTree.scope == "school")
+                    {
+                        try
+                        {
+                            syllabus = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>(syllabusTree.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                        }
+                        catch
+                        {
+                        }
+                        if (syllabus == null)
+                        {
+                            syllabus = new Syllabus();
+                            syllabus.id = syllabusTree.id;
+                            syllabus.children = nodes;
+                            syllabus.code = $"Syllabus-{syllabusTree.volumeId}";
+                            syllabus.pk = "Syllabus";
+                            syllabus.ttl = -1;
+                            syllabus.volumeId = syllabusTree.volumeId;
+                            syllabus.scope = syllabusTree.scope;
+                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                        }
+                        else
+                        {
+                            syllabus.children = nodes;
+                            syllabusTree.auth = syllabus.auth;
+                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabus,syllabus.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                        }
+
+                    }
+                    else {
+                        try
+                        {
+                            syllabus = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>(syllabusTree.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                        }
+                        catch
+                        {
+                        }
+                        if (syllabus == null)
+                        {
+                            syllabus = new Syllabus();
+                            syllabus.id = syllabusTree.id;
+                            syllabus.children = nodes;
+                            syllabus.code = $"Syllabus-{syllabusTree.volumeId}";
+                            syllabus.pk = "Syllabus";
+                            syllabus.ttl = -1;
+                            syllabus.volumeId = syllabusTree.volumeId;
+                            syllabus.scope = syllabusTree.scope;
+                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                        }
+                        else
+                        {
+                            syllabus.children = nodes;
+                            syllabusTree.auth = syllabus.auth;
+                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                        }
+                    }
                 }
-                else
-                {
-                    await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{request.id}"));
+                else {
+                    string id = Guid.NewGuid().ToString();
+                    syllabusTree.id = id;
+                    Syllabus syllabus = new Syllabus {
+                        id = id,
+                        code = $"Syllabus-{syllabusTree.volumeId}",
+                        pk = "Syllabus",
+                        ttl = -1,
+                        volumeId=syllabusTree.volumeId,
+                        children=nodes,
+                        scope = syllabusTree.scope
+                    };
+                    if (syllabusTree.scope == "school") {
+                        await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                    } else {
+                        await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                    }
                 }
-                List<SyllabusTree> trees = SyllabusService.ListToTree(nodes);
-                tts.Add(trees);
             }
-
-            request.trees = new List<SyllabusTree>() ;
-            tts.ForEach(x => request.trees.AddRange(x));
             return Ok(request);
         }
 
- 
-
+        /*
+            {"code":"册别code:0baf00db-0768-4b62-a8f7-280f6bcebf71","scope":"school"}
+         */
         /// <summary>
         /// 查找课纲 
         /// </summary>
@@ -237,39 +148,41 @@ namespace TEAMModelOS.Controllers
             var client = _azureCosmos.GetCosmosClient();
             if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
             if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
-            SyllabusTreeNode tree = null;
-            string vcode = null;
-            List<List<SyllabusTree>> tts = new List<List<SyllabusTree>>();
+           
+            List<SyllabusTreeNode> treeNodes = new List<SyllabusTreeNode>();
             try {
                 if (scope.ToString().Equals("school"))
                 {
                     await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Syllabus>(queryText: $"select value(c) from c ",
                     requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{code}") }))
                     {
-                        vcode = item.volumeId;
                         List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
-                        tts.Add(trees);
+                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope =item.scope, trees = trees ,volumeId=item.volumeId,auth=item.auth};
+                        treeNodes.Add(tree);
                     }
-                    tree = new SyllabusTreeNode() { id = vcode,  scope = "school", trees= new List<SyllabusTree>() };
-                    tts.ForEach(x => tree.trees.AddRange(x));
+                    
                 }
                 else
                 {
                     await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Syllabus>(queryText: $"select value(c) from c ",
-                    requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{code}") }))
+                     requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{code}") }))
                     {
-                        vcode = item.volumeId;
                         List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
-                        tts.Add(trees);
+                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth };
+                        treeNodes.Add(tree);
                     }
-                    tree = new SyllabusTreeNode() { id = vcode, scope = "school", trees = new List<SyllabusTree>() };
-                    tts.ForEach(x => tree.trees.AddRange(x)); 
                 }
-                return Ok(new { tree });
+                return Ok(new { tree= treeNodes });
             } catch (Exception ex) {
-                return Ok(new { tree});
+                await _dingDing.SendBotMsg($"OS,{_option.Location},common/syllabus/find-id\n{ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return Ok(new { tree= treeNodes });
             }
         }
+
+        /*
+            {"id":"章节id","code":"册别id","scope":"school/private"}
+         */
+
         /// <summary>
         /// 删除章节
         /// </summary>
@@ -294,82 +207,5 @@ namespace TEAMModelOS.Controllers
                 return Ok(new { code = response.Status });
             }
         }
-
-
-     
-
-        private async Task<List<Tnode>> FindByPid(Tnode data, List<Tnode> nodes, List<Tnode> nodedata)
-        {
-            foreach (Tnode syllabus in nodedata)
-            {
-                if (syllabus.pid == data.id)
-                {
-                    nodes.Add(syllabus);
-                    await FindByPid(syllabus, nodes, nodedata);
-                }
-            }
-            return nodes;
-        }
-
-        
-        //private async Task<List<Syllabus>> SaveOrUpdateToNodes(List<Tnode> syllabusNodes)
-        //{
-        //    List<Syllabus> syllabuses;
-
-        //   var  data = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>(  syllabusNodes[0].code ,new Azure.Cosmos.PartitionKey(""));
-        //    if (data.IsEmpty())
-        //    {
-        //        var syllabus = new Syllabus { id = syllabusNodes[0].code, code = syllabusNodes[0].code, children = new List<SyllabusNode>() };
-        //        await _azureCosmos.SaveOrUpdate(syllabus);
-        //        data = new List<Syllabus>() { syllabus };
-        //    }
-        //    List<SyllabusNode> syllabusNodes1 = new List<SyllabusNode>();
-        //    if (data.IsNotEmpty())
-        //    {
-        //        syllabusNodes1.AddRange(data[0].children);
-        //        //replace
-        //        for (int i = 0; i < data[0].children.Count; i++)
-        //        {
-        //            for (int j = 0; j < syllabusNodes.Count; j++)
-        //            {
-        //                if (data[0].children[i].id == syllabusNodes[j].id && data[0].children[i].code == syllabusNodes[j].code)
-        //                {
-        //                    syllabusNodes1.Remove(data[0].children[i]);
-        //                    syllabusNodes1.Add(syllabusNodes[j]);
-        //                    syllabusNodes.Remove(syllabusNodes[j]);
-        //                }
-        //            }
-        //        }
-        //        data[0].children = syllabusNodes1;
-
-        //        //新增
-        //        data[0].children.AddRange(syllabusNodes);
-
-        //        if (data[0].children.IsNotEmpty())
-        //        {
-        //            var len = data[0].children.Count;
-        //            for (int i = 0; i < len; i++)
-        //            {
-        //                if (data[0].children[i].items.IsNotEmpty())
-        //                {
-        //                    data[0].children[i].item = true;
-        //                }
-        //                if (data[0].children[i].resources.IsNotEmpty())
-        //                {
-        //                    data[0].children[i].resource = true;
-        //                }
-        //            }
-        //        }
-        //        syllabuses = await _azureCosmos.SaveOrUpdateAll<Syllabus>(data);
-
-        //    }
-        //    else
-        //    {
-        //        throw new BizException("保存失败", ResponseCode.FAILED);
-
-        //    }
-
-        //    return syllabuses;
-        //}
     }
 }

+ 2 - 4
TEAMModelOS/Controllers/Syllabus/VolumeController.cs

@@ -217,15 +217,13 @@ namespace TEAMModelOS.Controllers
                 try {
                     if (request.scope.Equals("school"))
                     {
-                        Volume volume = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReadItemAsync<Volume>(request.id, new PartitionKey(request.code));
+                      //  Volume volume = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReadItemAsync<Volume>(request.id, new PartitionKey(request.code));
                         //保留授权
-                        request.auth = volume.auth;
                         await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Volume>(request, request.id, new Azure.Cosmos.PartitionKey(request.code));
                     }
                     else if (request.scope.Equals("private")) {
-                        Volume volume = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Volume>(request.id, new PartitionKey(request.code));
+                       // Volume volume = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Volume>(request.id, new PartitionKey(request.code));
                         //保留授权
-                        request.auth = volume.auth;
                         await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Volume>(request, request.id, new Azure.Cosmos.PartitionKey(request.code));
                     }