257 次代码提交 276d6b3bf6 ... 92ff4cb543

作者 SHA1 备注 提交日期
  osbert 92ff4cb543 合併兩版首頁砍掉不用的頁面 4 年之前
  osbert 3e02a503ba Merge branch 'develop5.0' into TPE/develop5.0 4 年之前
  CrazyIter_Bin 661d7e64fe 模组检测更新 4 年之前
  liqk 784a5575a8 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk ec6f5dfe6a 调整登录页 4 年之前
  OnePsycho a6483906bc Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho eef333ca5a LOGO调整 4 年之前
  CrazyIter_Bin 2c821a8d04 容器上传记录删除失败解决 4 年之前
  CrazyIter_Bin 43666dab2e 更新测试 4 年之前
  OnePsycho 51661d299d 处理校本个人入库的调整 4 年之前
  OnePsycho d2026e9091 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho e72fdf0631 调整chooseContent 4 年之前
  XW 9b1c4ad08b Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW f2a4aabd80 开放平台多语言 4 年之前
  liqk 0150702707 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 194a84cd66 登录模块多语配置 4 年之前
  OnePsycho 920698da38 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho c985609558 知识点修改updated 4 年之前
  XW 0a6fa5da17 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW 21aaed2b1c 调整开放平台页面 4 年之前
  OnePsycho 4fa587b5eb Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 0eec36ac7b 修改chooseContent 4 年之前
  CrazyIter_Bin bcc59fcbb4 Merge branch 'develop5.0' into develop5.0-tmd 4 年之前
  liqk 34d092cdf4 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk f25989ee05 调整登录页 4 年之前
  CrazyIter_Bin 66ad381259 合并5.0 4 年之前
  JAELYS 226d015c29 add client test sse prog 4 年之前
  CrazyIter_Bin 350eea7f18 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 202c787393 提交sse 4 年之前
  OnePsycho e9651f8719 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho d86f5cc45c 课纲多语言&&资源列表样式&&上传后的link地址 4 年之前
  CrazyIter_Bin ce4b8d1473 解决blob容器大小计算 4 年之前
  OnePsycho 5f3be4ded2 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 3db9ffde01 试卷从Blob读取后添加scope 4 年之前
  liqk 3932640372 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 476aaecc4f 个人内容参数 4 年之前
  OnePsycho 1e0ef7e250 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho df29fd2266 试卷页面缓存的判断&&删除课纲节点和册别对应的资源文件 4 年之前
  XW 3a6ec6bf4c Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW 05949f6c75 调整学生端css 4 年之前
  liqk b58bbd9f8b Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 4624d6316f 优化UI 4 年之前
  CrazyIter_Bin 010f2dbb8a Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin f7a8d10f79 检查资源链接是否被其他结构关联 4 年之前
  liqk 7e70b51d8f 多语系 4 年之前
  liqk d57b61331e 完成扫码加入名单的功能 4 年之前
  liqk b1f480cfd5 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk d96b2f3a7c 完成大云账号管理功能 4 年之前
  CrazyIter_Bin baf4671096 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin dece1365eb 多个ids 4 年之前
  XW 3a5623e900 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW f9c4289abf 调整开放平台 4 年之前
  CrazyIter_Bin d114999323 课纲数据结构调整 4 年之前
  zhouj1203@hotmail.com fba7b37146 Function 学年计算 4 年之前
  zhouj1203@hotmail.com 66c56a4034 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  zhouj1203@hotmail.com 8ef3b1fa73 调整学年推算方式 4 年之前
  OnePsycho f1ad412080 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 547d95b36e 个人课纲选校本试题的入库操作 4 年之前
  zhouj1203@hotmail.com 334cd2a02b Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  zhouj1203@hotmail.com ee57b2e272 阅卷相关调整 4 年之前
  zhouj1203@hotmail.com ba21768398 学情年级分组结算 4 年之前
  XW 4c92532ec2 /// <summary> 4 年之前
  CrazyIter_Bin ed546063a6 调整agree 4 年之前
  CrazyIter_Bin 1a6e49d104 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 62c3690bda type rlwd 4 年之前
  liqk c16c863bc1 注释tab 4 年之前
  liqk 9406c1cf33 添加开放平台路由 4 年之前
  liqk 90357b402f 个人中心路由 4 年之前
  OnePsycho 58253e28f4 修改poptip 4 年之前
  OnePsycho 52ba18ea37 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho caeeaffdc4 课纲复制分享的章节&&试题试卷的复制操作 4 年之前
  liqk 5a16bbcdf7 hover 4 年之前
  liqk 993a214940 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 0feb5be2e0 调整个人中心 4 年之前
  CrazyIter_Bin 550f7a8b25 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 06d1ea3c9a 修改逻辑 4 年之前
  XW 466ffb9df6 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW 7c38c9d855 新增开放平台的域名等 4 年之前
  CrazyIter_Bin 5a7ce283a3 更新试卷 4 年之前
  CrazyIter_Bin 7b7a3dd9b1 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin ca5c2ac38e 课纲调整结构。 4 年之前
  liqk 8bad793c55 bug 4 年之前
  liqk d3cb5ad054 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 6ce3bf98ad 完善加入名单功能 4 年之前
  CrazyIter_Bin 6c2c389623 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin e289713fca 只读增加list权限 4 年之前
  XW c12b0e964f Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW 6a6836258f 删除不存在的活动 4 年之前
  CrazyIter_Bin cad5163727 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 19608d0952 删除课纲分享 4 年之前
  liqk 8533628541 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk b169b78aae 完成大陆站验证手机号API对接 4 年之前
  CrazyIter_Bin e25b320b1f 返回 status 4 年之前
  CrazyIter_Bin 4ca67de9ff 更新分享接口 4 年之前
  CrazyIter_Bin c816e2bad5 提交 4 年之前
  CrazyIter_Bin 0a0e3a121f 更新课纲数据结构 4 年之前
  CrazyIter_Bin 9ff0787593 返回创建时间 4 年之前
  CrazyIter_Bin 5ae532788a 共编分享更新数据结构 4 年之前
  OnePsycho 3102ef0ee5 完善自动组卷和手动组卷的总分自动分配功能 4 年之前
  liqk 3757730272 教师汇入模板多语系 4 年之前
  CrazyIter_Bin 938edf78d1 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 1618d0b913 教师默认空间 4 年之前
  liqk e3f9da7f46 细节调整 4 年之前
  CrazyIter_Bin 8558bcbc9d Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 723f207056 返回容器的大小。 4 年之前
  liqk 45efba9cca Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk bbf109038f 细节优化 4 年之前
  CrazyIter_Bin ab0df982c5 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 9d0ce167fd 数量统计bug 4 年之前
  liqk 72534b50b8 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 2d59b6c416 名单模板多语系 4 年之前
  OnePsycho b504a3567c Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 8336198b5f 答题卡返回上一层 4 年之前
  liqk 7d88e9775d 名词调整 4 年之前
  liqk e86060c764 排查vuex刷新流程,解决缓存数据bug 4 年之前
  liqk bd08f75ed5 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 8fe1be712f 多语系排查,名词调整 4 年之前
  OnePsycho c20c903232 富文本编辑器多语言配置 4 年之前
  liqk 71e3561105 画布配置项 4 年之前
  liqk 762ac55d7f Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 9cfda534b1 优化导入学生id和座号检查逻辑 4 年之前
  OnePsycho be751bbc24 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho cb118804cd 编辑器多语言配置 4 年之前
  liqk 781884f1af Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk fdb43f01e5 画布配置宽高 4 年之前
  XW 86993c0b26 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW 1c52a3c735 优化学生端代码 4 年之前
  liqk f465c433fa 阅卷设置页面多语系 4 年之前
  liqk a07f01eeaf Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 31f3f31aba 排查教师账号权限设置 4 年之前
  OnePsycho d852c5de98 加入试卷列表搜索功能 4 年之前
  OnePsycho 3906bd324c Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 8b7c36ffb3 问卷nbsp调整&&课纲节点个人试题试卷入库 4 年之前
  liqk f6f94faa8d 阅卷模块多语系 4 年之前
  liqk 6e71f991cf Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk f4e8aee37c 优化名词,调整多语系 4 年之前
  XW 5fdc91bc5d Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW a3dcf9ed09 修改被删除的投票和问卷显示 4 年之前
  liqk c45d66d34d 完成新增学生功能优化 4 年之前
  CrazyIter_Bin 674058a087 classYear 4 年之前
  CrazyIter_Bin 4dd4f7d27a Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin f7fa20b020 学生端活动数据返回 4 年之前
  OnePsycho 4e93421504 个人课纲调整 4 年之前
  CrazyIter_Bin 87e240509e school 必须设置取消 4 年之前
  CrazyIter_Bin 18a1102506 shcool 4 年之前
  CrazyIter_Bin 8eb80e8176 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 9e1a2ff48e 册别school 4 年之前
  OnePsycho dfafbcda75 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 29917fe393 校本课纲共编以及分享功能 4 年之前
  XW 61af39e7a5 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW 880af3b58a 代码格式 4 年之前
  CrazyIter_Bin 6d5f3f1032 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 14caabdf62 个人课纲分享 4 年之前
  liqk 66feaf19c5 加入名单UI 4 年之前
  liqk 017450ed44 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 7f373d7d5d 跟换阅卷批注图片 4 年之前
  CrazyIter_Bin d3a6838d4d Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin fc3cde97af 更新课纲auth条件 4 年之前
  OnePsycho be2287bc02 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 3e86f25f25 校本课纲共编权限 4 年之前
  CrazyIter_Bin 83e5e4b200 volumeId 调整 4 年之前
  liqk 7dd5b53696 优化间距 4 年之前
  liqk 09e09b2c47 bug 4 年之前
  liqk 5165507441 优化登录效果 4 年之前
  CrazyIter_Bin 3d6a3f5a30 Merge branch 'develop5.0-tmd' into develop5.0 4 年之前
  CrazyIter_Bin ddcf85629f Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin b178e69a89 update 4 年之前
  JAELYS 6994fc169d Merge branch 'develop5.0-tmd' into develop5.0 4 年之前
  liqk 7bf8c09c80 优化 4 年之前
  JAELYS 440d6f08e7 update 4 年之前
  liqk 807b852b22 添加教师汇入模板 4 年之前
  JAELYS f6ad28b56d Merge branch 'develop5.0-tmd' into develop5.0 4 年之前
  JAELYS 7dad5a219e fix settings.js 4 年之前
  liqk aea1e053ed 微信icon 4 年之前
  JAELYS 62b1da058a marge 4 年之前
  liqk 668741b1ba 删除多余文件 4 年之前
  liqk c7f0bbd923 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 5b8630529f 调整登录页面 4 年之前
  CrazyIter_Bin dab447792c Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 663bbaa459 完成端内通知到端外通知的接口。 4 年之前
  OnePsycho a65d2c7301 课纲修改调整&&消息通知 4 年之前
  CrazyIter_Bin 4308e764d0 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 262667bcbd 章节顺序返回 4 年之前
  liqk 3e4d4d6362 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk be24902e34 优化 4 年之前
  OnePsycho e90cb9e632 课纲结构调整拖拽调整以及保存机制调整 4 年之前
  CrazyIter_Bin 79f6422fa0 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 18ff7a57df 课纲数据结构 4 年之前
  liqk 53f03186e8 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 673eaaa912 添加首页mini课表 4 年之前
  CrazyIter_Bin 9cbcb06082 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 6753df54bd 册别更新保存课纲章节的id集合顺序。 4 年之前
  OnePsycho 9151c85ad1 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 7c41bff613 申请建立AI学校完善 4 年之前
  JAELYS 2b20520e02 add coretokenextensions 4 年之前
  CrazyIter_Bin 4749958186 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 997a2c7534 分享 4 年之前
  zhouj1203@hotmail.com 4119da1a36 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  zhouj1203@hotmail.com 552f6fbc3b 年级Index计算以及学生端排名计算 4 年之前
  CrazyIter_Bin b4c89d5a6d 获取分享的课纲 4 年之前
  CrazyIter_Bin aa2f28fae0 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 9fa012eccd 课纲的数据结构调整。 4 年之前
  OnePsycho 4dfed5076f Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 04c9403142 syllabusFix 4 年之前
  liqk c1079df439 优化学段筛选资源 4 年之前
  liqk 104523e3f0 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk e49a7fdf97 内容模块添加学段、学科和年级 4 年之前
  CrazyIter_Bin 94c84468c4 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 233bd52254 课纲数据结构保存 4 年之前
  liqk d55a79d05a 学生模块名字调整 4 年之前
  liqk db29f85006 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 45b745aaf5 菜单调整 4 年之前
  CrazyIter_Bin 7f4761eb98 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 4bddf9cbc2 钉钉异常通知 4 年之前
  liqk d2044a5191 菜单优化&qrcode文字&预览中&注释关联HiTeach 4 年之前
  liqk 788d02cd6e Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 36266cc5df 处理授权tab顺序 4 年之前
  CrazyIter_Bin 29b2b0f6bf 更新BlobLog 4 年之前
  CrazyIter_Bin 8cf9c43ee6 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 7ed34a4dcf blob上传修改 4 年之前
  OnePsycho c3f0d4f295 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 8657c0a50a fixExerciseList 4 年之前
  CrazyIter_Bin d909708df2 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 605f6d03a1 blob容器文件上传处理 4 年之前
  XW 2618115093 学生端多语言 4 年之前
  OnePsycho 36e17b10bc 学校设置多语言完善&&BaseFilter注释&&分页后的关闭详情 4 年之前
  OnePsycho aee71c84db Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 7010376a20 申请建立学校接口对接 4 年之前
  liqk b736993c16 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 334b25b44a title多语系配置 4 年之前
  CrazyIter_Bin 796578e8db Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin 0492b43b4d 申请学校通知接口 4 年之前
  XW 942703b1a8 教师端setting的颜色 4 年之前
  XW 43e0f0a064 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  XW d75274a3b8 调整评测页面布局 4 年之前
  CrazyIter_Bin ae13e89a27 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin ba0bdbee7f 内容增加学科 年级 4 年之前
  zhouj1203@hotmail.com 61b21561f0 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  zhouj1203@hotmail.com a2e44375d4 动态计算年级index 4 年之前
  liqk ffca8a2dff Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 8ed7a50c5d 对接保存批注功能 4 年之前
  OnePsycho ec31cbc597 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 6a92c4c196 学情首页年级下标修改&&答题卡考号调整 4 年之前
  liqk 59adfdc2a6 优化画布功能 4 年之前
  liqk ffb16424b1 多语系bug 4 年之前
  liqk 2ba61e2b51 bug 4 年之前
  liqk 42c097ee3a PDF预览&学生学号&阅卷配置 4 年之前
  OnePsycho 044aebd03d Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  OnePsycho 638c8c1c44 pdf预览build目录更改 4 年之前
  zhouj1203@hotmail.com c4ff21acef Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  zhouj1203@hotmail.com 20ced1bbd4 处理阅卷数据生成问题 4 年之前
  liqk a09dec0583 Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  liqk 06c8615c8a 阅卷优化 4 年之前
  CrazyIter_Bin 96de4a606e Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  CrazyIter_Bin d65654e799 调整课纲 4 年之前
  zhouj1203@hotmail.com 066f8d423b Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd 4 年之前
  zhouj1203@hotmail.com 2c4922413b 处理随机分配人数问题 4 年之前
共有 100 个文件被更改,包括 82840 次插入184 次删除
  1. 16 0
      Client/Client.csproj
  2. 67 0
      Client/Program.cs
  3. 143 0
      Client/SSE/ConnectedState.cs
  4. 55 0
      Client/SSE/ConnectingState.cs
  5. 37 0
      Client/SSE/DisconnectedState.cs
  6. 116 0
      Client/SSE/EventSource.cs
  7. 14 0
      Client/SSE/EventSourceState.cs
  8. 15 0
      Client/SSE/IConnectionState.cs
  9. 17 0
      Client/SSE/IServerResponse.cs
  10. 15 0
      Client/SSE/IWebRequester.cs
  11. 12 0
      Client/SSE/IWebRequesterFactory.cs
  12. 39 0
      Client/SSE/ServerResponse.cs
  13. 26 0
      Client/SSE/ServerSentEvent.cs
  14. 17 0
      Client/SSE/ServerSentEventReceivedEventArgs.cs
  15. 16 0
      Client/SSE/StateChangedEventArgs.cs
  16. 47 0
      Client/SSE/StringSplitter.cs
  17. 38 0
      Client/SSE/WatchDog.cs
  18. 30 0
      Client/SSE/WebRequester.cs
  19. 16 0
      Client/SSE/WebRequesterFactory.cs
  20. 3 3
      TEAMModelOS/Filter/ApiTokenAttribute.cs
  21. 38 0
      TEAMModelAPI/Startup.cs
  22. 1 2
      TEAMModelAPI/TEAMModelAPI.csproj
  23. 13 1
      TEAMModelAPI/appsettings.json
  24. 1 1
      TEAMModelFunction/ActivityHttpTrigger.cs
  25. 21 1
      TEAMModelFunction/TriggerCorrect.cs
  26. 29 6
      TEAMModelFunction/TriggerExam.cs
  27. 1 1
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs
  28. 4 1
      TEAMModelOS.SDK/DI/DingDing/DingDing.cs
  29. 171 0
      TEAMModelOS.SDK/Extension/CoreTokenExtensions.cs
  30. 2 2
      TEAMModelOS.SDK/Extension/JwtAuthExtension.cs
  31. 72 1
      TEAMModelOS.SDK/Models/Cosmos/Api/OpenApi.cs
  32. 4 1
      TEAMModelOS.SDK/Models/Cosmos/Common/Bloblog.cs
  33. 19 7
      TEAMModelOS.SDK/Models/Cosmos/Common/Inner/SyllabusTree.cs
  34. 61 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Scoring.cs
  35. 3 1
      TEAMModelOS.SDK/Models/Cosmos/Common/Snode.cs
  36. 22 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Syllabus.cs
  37. 12 0
      TEAMModelOS.SDK/Models/Cosmos/Common/TmdInfo.cs
  38. 4 17
      TEAMModelOS.SDK/Models/Cosmos/Common/Volume.cs
  39. 1 1
      TEAMModelOS.SDK/Models/Cosmos/Common/Vote.cs
  40. 1 1
      TEAMModelOS.SDK/Models/Cosmos/School/Class.cs
  41. 1 0
      TEAMModelOS.SDK/Models/Cosmos/School/Paper.cs
  42. 0 111
      TEAMModelOS.SDK/Models/Cosmos/Teacher/Favorite.cs
  43. 127 0
      TEAMModelOS.SDK/Models/Cosmos/Teacher/Share.cs
  44. 77 0
      TEAMModelOS.SDK/Models/Service/NotificationService.cs
  45. 14 0
      TEAMModelOS.SDK/Models/Table/tmdInfo.cs
  46. 4 0
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  47. 7 1
      TEAMModelOS.sln
  48. 2 0
      TEAMModelOS/ClientApp/package.json
  49. 14827 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.js
  50. 1 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.js.map
  51. 313 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.sandbox.js
  52. 1 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.sandbox.js.map
  53. 65293 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.worker.js
  54. 1 0
      TEAMModelOS/ClientApp/public/pdfBuild/pdf.worker.js.map
  55. 1 1
      TEAMModelOS/ClientApp/public/web/viewer.html
  56. 5 5
      TEAMModelOS/ClientApp/public/web/viewer.js
  57. 1 1
      TEAMModelOS/ClientApp/public/web/viewer.js.map
  58. 73 9
      TEAMModelOS/ClientApp/src/api/blob.js
  59. 7 0
      TEAMModelOS/ClientApp/src/api/evaluation.js
  60. 2 0
      TEAMModelOS/ClientApp/src/api/index.js
  61. 8 1
      TEAMModelOS/ClientApp/src/api/openMgmt.js
  62. 6 1
      TEAMModelOS/ClientApp/src/api/schoolSetting.js
  63. 23 0
      TEAMModelOS/ClientApp/src/api/service.js
  64. 5 0
      TEAMModelOS/ClientApp/src/api/studentWeb.js
  65. 15 0
      TEAMModelOS/ClientApp/src/api/syllabus.js
  66. 164 3
      TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html
  67. 31 3
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css
  68. 1 1
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js
  69. 49 0
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json
  70. 二进制
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf
  71. 二进制
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff
  72. 二进制
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2
  73. 二进制
      TEAMModelOS/ClientApp/src/assets/image/1-1.jpg
  74. 二进制
      TEAMModelOS/ClientApp/src/assets/login/1-1.jpg
  75. 二进制
      TEAMModelOS/ClientApp/src/assets/login/1-2.png
  76. 二进制
      TEAMModelOS/ClientApp/src/assets/login/1-3.png
  77. 二进制
      TEAMModelOS/ClientApp/src/assets/login/1-4.png
  78. 二进制
      TEAMModelOS/ClientApp/src/assets/login/1-5.png
  79. 二进制
      TEAMModelOS/ClientApp/src/assets/login/1-7.png
  80. 二进制
      TEAMModelOS/ClientApp/src/assets/login/2-1.png
  81. 二进制
      TEAMModelOS/ClientApp/src/assets/login/2-2.jpg
  82. 二进制
      TEAMModelOS/ClientApp/src/assets/login/3-1.jpg
  83. 二进制
      TEAMModelOS/ClientApp/src/assets/login/3-2.png
  84. 1 0
      TEAMModelOS/ClientApp/src/assets/login/icon_student.svg
  85. 1 0
      TEAMModelOS/ClientApp/src/assets/login/icon_teacher.svg
  86. 1 0
      TEAMModelOS/ClientApp/src/assets/login/ies5_logo_2.svg
  87. 二进制
      TEAMModelOS/ClientApp/src/assets/login/login_bg.jpg
  88. 54 0
      TEAMModelOS/ClientApp/src/assets/mark/0.svg
  89. 47 0
      TEAMModelOS/ClientApp/src/assets/mark/1.svg
  90. 57 0
      TEAMModelOS/ClientApp/src/assets/mark/2.svg
  91. 51 0
      TEAMModelOS/ClientApp/src/assets/mark/3.svg
  92. 63 0
      TEAMModelOS/ClientApp/src/assets/mark/4.svg
  93. 94 0
      TEAMModelOS/ClientApp/src/assets/mark/5.svg
  94. 77 0
      TEAMModelOS/ClientApp/src/assets/mark/6.svg
  95. 62 0
      TEAMModelOS/ClientApp/src/assets/mark/7.svg
  96. 54 0
      TEAMModelOS/ClientApp/src/assets/mark/8.svg
  97. 二进制
      TEAMModelOS/ClientApp/src/assets/mark/img0.jpg
  98. 二进制
      TEAMModelOS/ClientApp/src/assets/mark/img1.jpg
  99. 二进制
      TEAMModelOS/ClientApp/src/assets/mark/img2.jpg
  100. 0 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/event-list-new.css

+ 16 - 0
Client/Client.csproj

@@ -0,0 +1,16 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="5.0.3" />
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
+    <PackageReference Include="Twilio" Version="5.55.0" />
+  </ItemGroup>
+
+</Project>

+ 67 - 0
Client/Program.cs

@@ -0,0 +1,67 @@
+using Client.SSE;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net.Http;
+using System.Security.Policy;
+using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using System.Threading;
+using System.Threading.Tasks;
+
+
+namespace Client
+{
+    class Program
+    {    
+        static void Main(string[] args)
+        {
+            //SSE
+            try
+            {
+                var cts = new CancellationTokenSource();
+                var header = new Dictionary<string, string>() { { "X-Auth-Name", "IES5" } };
+                var sse = new EventSource(new Uri("https://localhost:5001/service/sse"), header, 5000);
+                //var sse = new EventSource(new Uri("https://api2.teammodel.net/service/sse"), header, 5000);
+
+                sse.StateChanged += Sse_StateChanged;
+                sse.EventReceived += Sse_EventReceived;
+                sse.Start(cts.Token);
+
+                //cts?.Cancel(); 中斷SSE Client連線
+            }
+            catch (TaskCanceledException ex)
+            {
+                Console.WriteLine(ex.Message);
+            }
+            catch (AggregateException ex)
+            {
+                Console.WriteLine(ex.Message);
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine(ex.Message);
+            }
+            Console.ReadLine();
+        }
+
+        private static void Sse_EventReceived(object sender, ServerSentEventReceivedEventArgs e)
+        {
+            var mm = e.Message;
+            Console.WriteLine(mm.Data);
+        }
+
+
+        private static void Sse_StateChanged(object sender, StateChangedEventArgs e)
+        {
+            //CONNECTING 0 連線中
+            //OPEN 1 開啟
+            //CLOSED 2 關閉
+            var aa = e.State;
+
+            Console.WriteLine(aa.ToString());
+        }
+
+    }
+}

+ 143 - 0
Client/SSE/ConnectedState.cs

@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Net;
+using System.IO;
+using System.Threading.Tasks;
+using System.Threading;
+using System.Diagnostics;
+
+namespace Client.SSE
+{
+    public class ConnectedState : IConnectionState
+    {    
+
+        private IWebRequesterFactory mWebRequesterFactory;
+        private ServerSentEvent mSse = null;
+        private string mRemainingText = string.Empty;   // the text that is not ended with a lineending char is saved for next call.
+        private IServerResponse mResponse;
+        private Dictionary<string, string> headers;
+
+        public EventSourceState State { get { return EventSourceState.OPEN; } }
+
+        public ConnectedState(IServerResponse response, IWebRequesterFactory webRequesterFactory, Dictionary<string, string> headers)
+        {
+            mResponse = response;
+            mWebRequesterFactory = webRequesterFactory;
+            this.headers = headers;
+        }
+
+        public Task<IConnectionState> Run(Action<ServerSentEvent> msgReceived, CancellationToken cancelToken, Dictionary<string, string> headers)
+        {   
+            Task<IConnectionState> t = new Task<IConnectionState>(() =>
+            {
+                //using (mResponse)
+                {
+                    //using (var stream = mResponse.GetResponseStream())
+                    var stream = mResponse.GetResponseStream();
+                    {
+                        byte[] buffer = new byte[1024 * 8];
+                        var taskRead = stream.ReadAsync(buffer, 0, buffer.Length, cancelToken);
+
+                        try
+                        {
+                            taskRead.Wait(cancelToken);
+                        }
+                        catch (Exception ex)
+                        {
+                            Trace.WriteLine(ex, "ConnectedState.Run");
+                        }
+                        if (!cancelToken.IsCancellationRequested)
+                        {
+                            int bytesRead = taskRead.Result;
+                            if (bytesRead > 0) // stream has not reached the end yet
+                            {
+                                //Console.WriteLine("ReadCallback {0} bytesRead", bytesRead);
+                                string text = Encoding.UTF8.GetString(buffer, 0, bytesRead);
+                                text = mRemainingText + text;
+                                string[] lines = StringSplitter.SplitIntoLines(text, out mRemainingText);
+                                foreach (string line in lines)
+                                {
+                                    if (cancelToken.IsCancellationRequested) break;
+
+                                    // Dispatch message if empty lne
+                                    if (string.IsNullOrEmpty(line.Trim()) && mSse != null)
+                                    {
+                                        Trace.WriteLine("SSE Message received");
+                                        msgReceived(mSse);
+                                        mSse = null;
+                                    }
+                                    else if (line.StartsWith(":"))
+                                    {
+                                        // This a comment, just log it.
+                                        Trace.WriteLine("SSE A comment was received: " + line);
+                                    }
+                                    else
+                                    {
+                                        string fieldName = String.Empty;
+                                        string fieldValue = String.Empty;
+                                        if (line.Contains(':'))
+                                        {
+                                            int index = line.IndexOf(':');
+                                            fieldName = line.Substring(0, index);
+                                            fieldValue = line.Substring(index + 1).TrimStart();
+                                        }
+                                        else
+                                            fieldName = line;
+
+                                        if (String.Compare(fieldName, "event", true) == 0)
+                                        {
+                                            mSse = mSse ?? new ServerSentEvent();
+                                            mSse.EventType = fieldValue;
+                                        }
+                                        else if (String.Compare(fieldName, "data", true) == 0)
+                                        {
+                                            mSse = mSse ?? new ServerSentEvent();
+                                            mSse.Data = fieldValue + '\n';
+                                        }
+                                        else if (String.Compare(fieldName, "id", true) == 0)
+                                        {
+                                            mSse = mSse ?? new ServerSentEvent();
+                                            mSse.LastEventId = fieldValue;
+                                        }
+                                        else if (String.Compare(fieldName, "retry", true) == 0)
+                                        {
+                                            int parsedRetry;
+                                            if (int.TryParse(fieldValue, out parsedRetry))
+                                            {
+                                                mSse = mSse ?? new ServerSentEvent();
+                                                mSse.Retry = parsedRetry;
+                                            }
+                                        }
+                                        else
+                                        {
+                                            // Ignore this, just log it
+                                            Trace.WriteLine("SSE A unknown line was received: " + line);
+                                        }
+                                    }
+                                }
+
+                                if (!cancelToken.IsCancellationRequested)
+                                    return this;
+                            }
+                            else // end of the stream reached
+                            {
+                                Trace.WriteLine("SSE No bytes read. End of stream.");
+                            }
+                        }
+
+                        //stream.Dispose()
+                        //stream.Close();
+                        //mResponse.Close();
+                        //mResponse.Dispose();
+                        return new DisconnectedState(mResponse.ResponseUri, mWebRequesterFactory, headers);
+                    }
+                }
+            });
+
+            t.Start();
+            return t;
+        }
+    }
+}

+ 55 - 0
Client/SSE/ConnectingState.cs

@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Net;
+using System.IO;
+using System.Threading;
+using System.Diagnostics;
+
+namespace Client.SSE
+{
+    public class ConnectingState : IConnectionState
+    {      
+
+        private Uri mUrl;
+        private IWebRequesterFactory mWebRequesterFactory;
+        private Dictionary<string, string> headers;
+
+        public EventSourceState State { get { return EventSourceState.CONNECTING; } }
+
+        public ConnectingState(Uri url, IWebRequesterFactory webRequesterFactory, Dictionary<string, string> headers)
+        {
+            if (url == null) throw new ArgumentNullException("Url cant be null");
+            if (webRequesterFactory == null) throw new ArgumentNullException("Factory cant be null");
+            mUrl = url;
+            mWebRequesterFactory = webRequesterFactory;
+            this.headers = headers;
+        }
+
+        public Task<IConnectionState> Run(Action<ServerSentEvent> donothing, CancellationToken cancelToken, Dictionary<string, string> headers)
+        {
+            IWebRequester requester = mWebRequesterFactory.Create();
+            var taskResp = requester.Get(mUrl, headers);
+
+            return taskResp.ContinueWith<IConnectionState>(tsk => 
+            {
+                if (tsk.Status == TaskStatus.RanToCompletion && !cancelToken.IsCancellationRequested)
+                {
+                    IServerResponse response = tsk.Result;
+                    if (response.StatusCode == HttpStatusCode.OK)
+                    {
+                        return new ConnectedState(response, mWebRequesterFactory, headers);
+                    }
+                    else
+                    {
+                        Trace.WriteLine("Failed to connect to: " + mUrl.ToString() + response ?? (" Http statuscode: " + response.StatusCode));
+                    }
+                }
+
+                return new DisconnectedState(mUrl, mWebRequesterFactory, headers);
+            });
+        }
+    }
+}

+ 37 - 0
Client/SSE/DisconnectedState.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Client.SSE
+{
+    public class DisconnectedState : IConnectionState 
+    {
+        private Uri mUrl;
+        private IWebRequesterFactory mWebRequesterFactory;
+        private Dictionary<string, string> headers;
+
+        public EventSourceState State
+        {
+            get { return EventSourceState.CLOSED; }
+        }
+
+        public DisconnectedState(Uri url, IWebRequesterFactory webRequesterFactory, Dictionary<string, string> headers)
+        {
+            if (url == null) throw new ArgumentNullException("Url cant be null");
+            mUrl = url;
+            mWebRequesterFactory = webRequesterFactory;
+            this.headers = headers;
+        }
+
+        public Task<IConnectionState> Run(Action<ServerSentEvent> donothing, CancellationToken cancelToken, Dictionary<string, string> headers)
+        {
+            if(cancelToken.IsCancellationRequested)
+                return Task.Factory.StartNew<IConnectionState>(() => { return new DisconnectedState(mUrl, mWebRequesterFactory, headers); });
+            else
+                return Task.Factory.StartNew<IConnectionState>(() => { return new ConnectingState(mUrl, mWebRequesterFactory, headers); });
+        }
+    }
+}

+ 116 - 0
Client/SSE/EventSource.cs

@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using System.Threading;
+
+namespace Client.SSE
+{
+    public class EventSource
+    {   
+        public event EventHandler<StateChangedEventArgs> StateChanged;
+        public event EventHandler<ServerSentEventReceivedEventArgs> EventReceived;
+
+        public CancellationTokenSource CancellationToken { get; set; }
+
+        private IWebRequesterFactory _webRequesterFactory = new WebRequesterFactory();
+        private int _timeout = 0;
+        public Uri Url { get; private set; }
+        public EventSourceState State { get { return CurrentState.State; } }
+        public string LastEventId { get; private set; }
+        private IConnectionState mCurrentState = null;
+        private CancellationToken mStopToken;
+        private CancellationTokenSource mTokenSource = new CancellationTokenSource();
+        private Dictionary<string, string> _headers;
+
+        private IConnectionState CurrentState
+        {
+            get { return mCurrentState; }
+            set
+            {
+                if (!value.Equals(mCurrentState))
+                {
+                    StringBuilder sb = new StringBuilder("State changed from ");
+                    sb.Append(mCurrentState == null ? "Unknown" : mCurrentState.State.ToString());
+                    sb.Append(" to ");
+                    sb.Append(value == null ? "Unknown" : value.State.ToString());
+                    Trace.WriteLine(sb.ToString());
+                    mCurrentState = value;
+                    OnStateChanged(mCurrentState.State);
+                }
+            }
+        }
+
+        public EventSource(Uri url, int timeout)
+        {
+            Initialize(url, timeout);
+        }
+
+        public EventSource(Uri url, Dictionary<string, string> headers, int timeout)
+        {
+            _headers = headers;
+            Initialize(url, timeout);
+        }
+
+        /// <summary>
+        /// Constructor for testing purposes
+        /// </summary>
+        /// <param name="factory">The factory that generates the WebRequester to use.</param>
+        public EventSource(Uri url, IWebRequesterFactory factory)
+        {
+            _webRequesterFactory = factory;
+            Initialize(url, 0);
+        }
+
+        private void Initialize(Uri url, int timeout)
+        {
+            _timeout = timeout;
+            Url = url;
+            CurrentState = new DisconnectedState(Url, _webRequesterFactory, _headers);
+            Trace.WriteLine("SSE EventSource created for " + url.ToString());
+        }
+
+
+        /// <summary>
+        /// Start the EventSource. 
+        /// </summary>
+        /// <param name="stopToken">Cancel this token to stop the EventSource.</param>
+        public void Start(CancellationToken stopToken)
+        {
+            if (State == EventSourceState.CLOSED)
+            {
+                mStopToken = stopToken;
+                mTokenSource = CancellationTokenSource.CreateLinkedTokenSource(stopToken);
+                Run();
+            }
+        }
+
+        protected void Run()
+        {
+            if (mTokenSource.IsCancellationRequested && CurrentState.State == EventSourceState.CLOSED)
+                return;
+
+            mCurrentState.Run(this.OnEventReceived, mTokenSource.Token, _headers).ContinueWith(cs =>
+            {
+                CurrentState = cs.Result;
+                Run();
+            });
+        }
+
+        protected void OnEventReceived(ServerSentEvent sse)
+        {
+            if (EventReceived != null)
+            {
+                EventReceived(this, new ServerSentEventReceivedEventArgs(sse));
+            }
+        }
+
+        protected void OnStateChanged(EventSourceState newState)
+        {
+            if (StateChanged != null)
+            {
+                StateChanged(this, new StateChangedEventArgs(newState));
+            }
+        }
+    }
+}

+ 14 - 0
Client/SSE/EventSourceState.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Client.SSE
+{
+    public enum EventSourceState
+    {
+        CONNECTING,
+        OPEN,
+        CLOSED 
+    }
+}

+ 15 - 0
Client/SSE/IConnectionState.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Client.SSE
+{
+    public interface IConnectionState
+    {
+        EventSourceState State { get; }
+        Task<IConnectionState> Run(Action<ServerSentEvent> MsgReceivedCallback, CancellationToken cancelToken, Dictionary<string, string> headers);
+    }
+}

+ 17 - 0
Client/SSE/IServerResponse.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Client.SSE
+{
+    public interface IServerResponse
+    {
+        HttpStatusCode StatusCode { get; }
+
+        System.IO.Stream GetResponseStream();
+
+        Uri ResponseUri { get; }
+    }
+}

+ 15 - 0
Client/SSE/IWebRequester.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Client.SSE
+{
+    public interface IWebRequester
+    {
+        Task<IServerResponse> Get(Uri url, Dictionary<string, string> headers = null);
+
+    }
+}

+ 12 - 0
Client/SSE/IWebRequesterFactory.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Client.SSE
+{
+    public interface IWebRequesterFactory
+    {
+        IWebRequester Create();
+    }
+}

+ 39 - 0
Client/SSE/ServerResponse.cs

@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Client.SSE
+{
+    public class ServerResponse : IServerResponse
+    {
+        private System.Net.HttpWebResponse mHttpResponse;
+
+        public ServerResponse(System.Net.WebResponse webResponse)
+        {
+            this.mHttpResponse = webResponse as HttpWebResponse;
+        }
+
+        public HttpStatusCode StatusCode
+        {
+            get
+            {
+                return mHttpResponse.StatusCode;
+            }
+        }
+
+        public System.IO.Stream GetResponseStream()
+        {
+            return mHttpResponse.GetResponseStream();
+        }
+
+        public Uri ResponseUri
+        {
+            get
+            {
+                return mHttpResponse.ResponseUri;
+            }
+        }
+    }
+}

+ 26 - 0
Client/SSE/ServerSentEvent.cs

@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Client.SSE
+{
+    public class ServerSentEvent
+    {
+        public string LastEventId { get; set; }
+        public string EventType { get; set; }
+        public string Data { get; set; }
+        public int? Retry { get; set; }
+
+        public override string ToString()
+        {
+            StringBuilder sb = new StringBuilder();
+            sb.Append("EventType: ").Append(EventType).AppendLine();
+            sb.Append("Data: ").Append(Data).AppendLine();
+            sb.Append("LastEventId: ").Append(LastEventId).AppendLine();
+            if(Retry.HasValue)
+                sb.Append("Retry: ").Append(Retry.Value).AppendLine();
+            return sb.ToString();
+        }
+    }
+}

+ 17 - 0
Client/SSE/ServerSentEventReceivedEventArgs.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Client.SSE
+{
+    public class ServerSentEventReceivedEventArgs : EventArgs
+    {
+        public ServerSentEvent Message { get; private set; }
+        public ServerSentEventReceivedEventArgs(ServerSentEvent message)
+        {
+            Message = message;
+        }
+
+    }
+}

+ 16 - 0
Client/SSE/StateChangedEventArgs.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Client.SSE
+{
+    public class StateChangedEventArgs : EventArgs
+    {
+        public EventSourceState State { get; private set; }
+        public StateChangedEventArgs(EventSourceState state)
+        {
+            State = state;
+        }
+    }
+}

+ 47 - 0
Client/SSE/StringSplitter.cs

@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Client.SSE
+{
+    public class StringSplitter
+    {
+        public static string[] SplitIntoLines(string text, out string remainingText)
+        {
+            List<string> lines = new List<string>();
+
+            //bool endFound = false;
+            //bool searchingForFirstChar = true;
+            int lineLength = 0;
+            char previous = char.MinValue;
+            for (int i = 0; i < text.Length; i++)
+            {
+                char c = text[i];
+                if (c == '\n' || c == '\r')
+                {
+                    bool isCRLFPair = previous=='\r' && c == '\n';
+
+                    if (!isCRLFPair)
+                    {
+                        string line = text.Substring(i - lineLength, lineLength);
+                        lines.Add(line);
+                    }
+
+                    lineLength = 0;
+                }
+                else
+                {
+                    lineLength++;
+                }
+                previous = c;
+            }
+
+            // Save the last chars that is not followed by a lineending.
+            remainingText = text.Substring(text.Length - lineLength);
+
+            return lines.ToArray();
+        }
+    }
+}

+ 38 - 0
Client/SSE/WatchDog.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Client.SSE
+{
+    public class Watchdog
+    {
+        private long _timeout;
+        private Timer _timer;
+        public event EventHandler TimerExpired;
+
+        public void Start()
+        {
+            _timer = new Timer(new TimerCallback(OnTimerExpired), null, 0, _timeout);
+        }
+
+        public void Reset()
+        {
+            _timer.Change(0, _timeout);
+        }
+
+        private void OnTimerExpired(object State)
+        {
+            _timer.Change(Timeout.Infinite, Timeout.Infinite);
+            if (TimerExpired != null)
+                TimerExpired(this, new EventArgs());
+        }
+
+        public Watchdog(long timeout)
+        {
+            if (timeout < 1) throw new ArgumentOutOfRangeException("timeout", "timeout muste be greater than zero.");
+        }
+    }
+}

+ 30 - 0
Client/SSE/WebRequester.cs

@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Threading.Tasks;
+
+namespace Client.SSE
+{
+    public class WebRequester : IWebRequester
+    {
+        public Task<IServerResponse> Get(Uri url, Dictionary<string, string> headers = null)
+        {
+            var wreq = (HttpWebRequest)WebRequest.Create(url);
+            wreq.Method = "GET";
+            wreq.Proxy = null;
+
+            if (headers != null)
+            {
+                foreach (var header in headers)
+                {
+                    wreq.Headers.Add(header.Key, header.Value);
+                }
+            }
+
+            var taskResp = Task.Factory.FromAsync<WebResponse>(wreq.BeginGetResponse,
+                wreq.EndGetResponse, null).ContinueWith<IServerResponse>(t => new ServerResponse(t.Result));
+            return taskResp;
+
+        }
+    }
+}

+ 16 - 0
Client/SSE/WebRequesterFactory.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Client.SSE
+{
+    public class WebRequesterFactory : IWebRequesterFactory
+    {
+        public IWebRequester Create()
+        {
+            return new WebRequester();
+        }
+    }
+}

+ 3 - 3
TEAMModelOS/Filter/ApiTokenAttribute.cs

@@ -48,9 +48,9 @@ namespace TEAMModelOS.Filter
                     jti = jwt.Payload.Jti;
                     name = jwt.Claims.FirstOrDefault(claim => claim.Type == "name")?.Value;
                     //处理限流问题
-                    if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(school) || string.IsNullOrEmpty(name) || string.IsNullOrEmpty(jti))
+                    if (!string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(school) && !string.IsNullOrEmpty(name)&& !string.IsNullOrEmpty(jti))
                     {
-                        context.Result = new BadRequestResult();
+                        pass = true;
                     }
                     else { 
                         
@@ -64,7 +64,7 @@ namespace TEAMModelOS.Filter
                     context.HttpContext.Items.Add("School", school);
                 }
                 else
-                    context.Result = new BadRequestResult();
+                    context.Result = new UnauthorizedResult();
             }
 
             public void OnResourceExecuted(ResourceExecutedContext context)

+ 38 - 0
TEAMModelAPI/Startup.cs

@@ -10,7 +10,11 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
+using TEAMModelOS.Models;
 using TEAMModelOS.SDK.DI;
+using System.IdentityModel.Tokens.Jwt;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.IdentityModel.Tokens;
 
 namespace TEAMModelAPI
 {
@@ -27,6 +31,37 @@ namespace TEAMModelAPI
         // This method gets called by the runtime. Use this method to add services to the container.
         public void ConfigureServices(IServiceCollection services)
         {
+           
+            JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
+            services.AddAuthentication(options => options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme)
+                .AddJwtBearer(options => //AzureADJwtBearer
+                {
+                    //options.SaveToken = true; //驗證令牌由服務器生成才有效,不適用於服務重啟或分布式架構
+                    options.Authority = Configuration["Option:Authority"];
+                    options.Audience = Configuration["Option:Audience"];
+                    options.RequireHttpsMetadata = true;
+                    options.TokenValidationParameters = new TokenValidationParameters
+                    {
+                        RoleClaimType = "roles",
+                        ValidAudiences = new string[] { Configuration["Option:Audience"], $"api://{Configuration["Option:Audience"]}" }
+                    };
+                    options.Events = new JwtBearerEvents();
+                    //下列事件有需要紀錄則打開
+                    //options.Events.OnMessageReceived = async context => { await Task.FromResult(0); };
+                    //options.Events.OnForbidden = async context => { await Task.FromResult(0); };
+                    //options.Events.OnChallenge = async context => { await Task.FromResult(0); };
+                    //options.Events.OnAuthenticationFailed = async context => { await Task.FromResult(0); };
+                    options.Events.OnTokenValidated = async context =>
+                    {
+                        if (!context.Principal.Claims.Any(x => x.Type == "http://schemas.microsoft.com/identity/claims/scope") //ClaimConstants.Scope
+                        && !context.Principal.Claims.Any(y => y.Type == "roles")) //ClaimConstants.Roles //http://schemas.microsoft.com/ws/2008/06/identity/claims/role
+                        {
+                            //TODO 需處理額外授權非角色及範圍的訪問異常紀錄
+                            throw new UnauthorizedAccessException("Neither scope or roles claim was found in the bearer token.");
+                        }
+                        await Task.FromResult(0);
+                    };
+                });
             //設定跨域請求
             services.AddCors(options =>
             {
@@ -50,6 +85,9 @@ namespace TEAMModelAPI
             services.AddHttpClient();
             services.AddHttpClient<DingDing>();
             services.AddAzureServiceBus(Configuration.GetValue<string>("Azure:ServiceBus:ConnectionString"));
+            //HttpContextAccessor,并用来访问HttpContext。(提供組件或非控制器服務存取HttpContext)
+            services.AddHttpContextAccessor();
+            services.Configure<Option>(options => Configuration.GetSection("Option").Bind(options));
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

+ 1 - 2
TEAMModelAPI/TEAMModelAPI.csproj

@@ -5,7 +5,6 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <ProjectReference Include="..\TEAMModelOS\TEAMModelOS.csproj" />
+    <ProjectReference Include="..\TEAMModelOS.SDK\TEAMModelOS.SDK.csproj" />
   </ItemGroup>
-
 </Project>

+ 13 - 1
TEAMModelAPI/appsettings.json

@@ -6,5 +6,17 @@
       "Microsoft.Hosting.Lifetime": "Information"
     }
   },
-  "AllowedHosts": "*"
+  "AllowedHosts": "*",
+  "Option": {
+    "Location": "China",
+    "LocationNum": "8",
+    "HostName": "localhost:5001",
+    "AllowedHosts": [ "localhost", "*.teammodel.cn", "*.teammodel.net", "*.habookaclass.biz", "test" ],
+    "Authority": "https://login.chinacloudapi.cn/4807e9cf-87b8-4174-aa5b-e76497d7392b/v2.0", //China:"https://login.chinacloudapi.cn/4807e9cf-87b8-4174-aa5b-e76497d7392b/v2.0", //Global:"https://login.microsoftonline.com/73a2bcc5-fe99-4566-aa8a-07e7bb287df1/v2.0"
+    "Audience": "72643704-b2e7-4b26-b881-bd5865e7a7a5", //China:"72643704-b2e7-4b26-b881-bd5865e7a7a5",Global:"8768b06f-c5c5-4b0c-abfb-d7ded354626d"
+    "Issuer": "www.teammodel.cn",
+    "JwtSecretKey": "fXO6ko/qyXeYrkecPeKdgXnuLXf9vMEtnBC9OB3s+aA=",
+    "Exp": 86400,
+    "IdTokenSalt": "8263692E2213497BB55E74792B7900B4"
+  }
 }

+ 1 - 1
TEAMModelFunction/ActivityHttpTrigger.cs

@@ -411,7 +411,7 @@ namespace TEAMModelFunction
             }
             List<ItemCond> itemConds = new List<ItemCond>();
             items.GroupBy(x => x.periodId).ToList().ForEach( x=> {
-                ItemCond cond = new ItemCond() { id=x.Key,code=$"ItemCond-hbcn" };
+                ItemCond cond = new ItemCond() { id=x.Key,code=$"ItemCond-hbcn" ,pk= "ItemCond" ,ttl=-1};
                 x.ToList().ForEach(y => {
                    ItemService.CountItemCond(y, null, cond);
                 });

+ 21 - 1
TEAMModelFunction/TriggerCorrect.cs

@@ -10,6 +10,8 @@ using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos;
+using TEAMModelOS.SDK.Models.Cosmos.Common;
+using TEAMModelOS.SDK.Models.Table;
 
 namespace TEAMModelFunction
 {
@@ -129,12 +131,30 @@ namespace TEAMModelFunction
                                     }
                                 }
                                 List<Task<bool>> tasks = new List<Task<bool>>();
+                                //初始化老师阅卷记录
+                                List<tmdInfo> tmds = new List<tmdInfo>();
+                                for (int i = 0; i < correct.num; i++) {
+                                    tmdInfo fo = new tmdInfo();
+                                    tmds.Add(fo);
+                                }
                                 foreach (ExamClassResult examClass in classResults)
                                 {
                                     foreach (string stuId in examClass.studentIds)
                                     {
                                         int index = examClass.studentIds.IndexOf(stuId);
-                                        tasks.Add(redisClient.HashSetAsync($"Exam:Scoring:{eid}-{subjectId}", stuId, new { tmdId = "" , ans = examClass.studentAnswers[index][0], score = examClass.studentScores[index] }.ToJsonString()));
+                                        if (index > -1) {
+                                            Scoring sc = new Scoring
+                                            {
+                                                blob = examClass.studentAnswers[index].Count > 0 ? examClass.studentAnswers[index][0] : "",
+                                                stuId =stuId,
+                                                examId = eid,
+                                                subjectId = subjectId,
+                                                scores = examClass.studentScores[index]
+                                            };
+                                        }
+                                        
+
+                                        tasks.Add(redisClient.HashSetAsync($"Exam:Scoring:{eid}-{subjectId}", stuId, new { tmdId = tmds, ans = examClass.studentAnswers[index].Count > 0 ? examClass.studentAnswers[index][0] : "", score = examClass.studentScores[index] }.ToJsonString()));
                                     }
 
                                 }

+ 29 - 6
TEAMModelFunction/TriggerExam.cs

@@ -206,11 +206,31 @@ namespace TEAMModelFunction
                                         var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.school}"));
                                         if (sresponse.Status == 200)
                                         {
+
                                             using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
                                             Class classroom = json.ToObject<Class>();
+                                            School sc = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>(info.school, new Azure.Cosmos.PartitionKey("Base"));
+                                            foreach (Period period in sc.period)
+                                            {
+                                                if (period.id.Equals(classroom.periodId))
+                                                {
+                                                    foreach (Semester semester in period.semesters)
+                                                    {
+                                                        if (semester.start == 1)
+                                                        {
+                                                            int year = DateTimeOffset.UtcNow.Year;
+                                                            int month = DateTimeOffset.UtcNow.Month;
+                                                            int day = DateTimeOffset.UtcNow.Day;
+                                                            int time =  month > semester.month ?  0 :  1;
+                                                            int eyear = year - time;
+                                                            result.gradeId = (eyear - classroom.year).ToString();
+                                                        }
+                                                    }
+                                                }
+                                            }
                                             //result.info.id = classroom.id;
                                             result.info.name = classroom.name;
-                                            result.gradeId = classroom.gradeId;
+                                            //result.gradeId = classroom.year.ToString();
                                             //处理班级人数
                                             await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id from c where c.classId = '{classroom.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Base-{info.school}") }))
                                             {
@@ -535,7 +555,8 @@ namespace TEAMModelFunction
                 int plcount = 0;
                 //存放并去重知识点
                 HashSet<string> kname = new HashSet<string>();
-                if (info.papers[no].knowledge.Count > 0) {
+                if (info.papers[no].knowledge.Count > 0)
+                {
                     info.papers[no].knowledge.ForEach(kno =>
                     {
                         kno.ForEach(k =>
@@ -631,7 +652,7 @@ namespace TEAMModelFunction
                         //await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(classResult, classResult.id, new Azure.Cosmos.PartitionKey($"{classResult.code}"));
                     }
                 }
-                
+
             }
             catch (Exception ex)
             {
@@ -672,7 +693,8 @@ namespace TEAMModelFunction
                             int phCount = 0;
                             int plCount = 0;
                             int pCount = 0;
-                            if (info.papers[no].field.Count > 0) {
+                            if (info.papers[no].field.Count > 0)
+                            {
                                 foreach (int str in info.papers[no].field)
                                 {
                                     if (str == knowledgeName[i])
@@ -720,7 +742,7 @@ namespace TEAMModelFunction
                                 pl.Add(plCount);
                                 double per = classResult.studentIds.Count > 0 ? Math.Round(score / classResult.studentIds.Count, 2) : 0;
                                 persent.Add(allScore > 0 ? per / allScore : 0);
-                            }                           
+                            }
                         }
                         classResult.fphc = ph;
                         classResult.fplc = pl;
@@ -858,7 +880,8 @@ namespace TEAMModelFunction
                         csRate.Add(classResult.studentIds.Count > 0 ? Math.Round(classSrate * 1.0 / classResult.studentIds.Count, 2) : 0 / allScore);
 
                     }
-                    else {
+                    else
+                    {
                         csRate.Add(0);
                     }
 

+ 1 - 1
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs

@@ -156,7 +156,7 @@ namespace TEAMModelOS.SDK.DI
                 BlobContainerSasPermissions blobContainerSasPermissions = BlobContainerSasPermissions.Read;
                 if (isRead)
                 {
-                    blobContainerSasPermissions = BlobContainerSasPermissions.Read;
+                    blobContainerSasPermissions = BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List;
                 }
                 else
                 {

+ 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智慧學校申請通知群
+
     }
 
 

+ 171 - 0
TEAMModelOS.SDK/Extension/CoreTokenExtensions.cs

@@ -0,0 +1,171 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using Microsoft.IdentityModel.Tokens;
+using Microsoft.Identity.Client;
+using System.ComponentModel;
+using System.Threading.Tasks;
+using Azure.Security.KeyVault.Secrets;
+using Azure.Core;
+using Azure.Identity;
+using System.Net.Http;
+using System.Collections.Concurrent;
+using System.Diagnostics;
+
+namespace TEAMModelOS.SDK.Extension
+{
+    public static class CoreTokenExtensions
+    {       //var issuer = Configuration.GetValue<string>("JwtSettings:Issuer");
+            //var signKey = Configuration.GetValue<string>("JwtSettings:SignKey");
+        private const string issuer = "account.teammodel";
+        //Azure AD 租用戶識別碼(國際、大陸)
+        private static List<string> tenantids = new List<string> { "73a2bcc5-fe99-4566-aa8a-07e7bb287df1", "4807e9cf-87b8-4174-aa5b-e76497d7392b" };
+        private static ConcurrentDictionary<string, KeyVaultSecret> KeyVaultSecrets { get; } = new ConcurrentDictionary<string, KeyVaultSecret>();
+              
+
+        #region  Access Token
+        /// <summary>
+        /// 產生AccessToken
+        /// </summary>
+        /// <param name="clientID"></param>
+        /// <param name="location">服務位置,Global or China ...</param>
+        /// <returns></returns>
+        public static async ValueTask<AuthenticationResult> CreateAccessToken(string clientID, string clientSecret, string location)
+        {
+            //從金鑰庫取出秘密,此作法讓所有端直接刷新金鑰,無需傳送秘密,SPA更適用
+            var secret = clientSecret ?? (await GetClientIDSecret(clientID, location)).Value;
+
+            var sts = Enum.Parse<STSEndpoint>(location, true);
+
+            IConfidentialClientApplication app;
+            app = ConfidentialClientApplicationBuilder.Create(clientID)
+                                                      .WithClientSecret(secret)
+                                                      .WithAuthority(new Uri(sts.GetDescriptionText()))
+                                                      .Build();
+            var scope = ((STSScope)sts).GetDescriptionText();
+            var result = await app.AcquireTokenForClient(new[] { scope }).ExecuteAsync();
+            return result;
+        }
+
+        /// <summary>
+        /// 驗證是否為公司Azure發行金鑰,支援大陸國際
+        /// </summary>
+        /// <param name="token"></param>
+        /// <returns></returns>
+        public static bool ValidateAccessToken(JwtSecurityToken token)
+        {
+            try
+            {
+                if (token.Payload.TryGetValue("tid", out var value) && value is string tokenTenantId)
+                {
+                    return tenantids.Contains(tokenTenantId);
+                }
+                return false;
+            }
+            catch (Exception)
+            {
+                return false;
+            }
+        }
+
+        public static bool ValidateIdToken(string token, string salt)
+        {
+            try
+            {
+                var handler = new JwtSecurityTokenHandler();
+                var validationParameters = new TokenValidationParameters
+                {
+                    RequireExpirationTime = true,
+                    ValidateIssuer = false,
+                    ValidateAudience = false,
+                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
+                    ValidateLifetime = false,
+                    //LifetimeValidator = LifetimeValidator,
+                    ClockSkew = TimeSpan.Zero                    
+                };
+                ClaimsPrincipal principal = handler.ValidateToken(token, validationParameters, out SecurityToken securityToken);
+                return true;
+            }
+            catch(Exception ex)
+            {
+                Trace.WriteLine(ex.Message);
+                return false;
+            }
+        }
+        #endregion
+
+        private static async ValueTask<KeyVaultSecret> GetClientIDSecret(string clientID, string location)
+        {   //Azure 金鑰庫處理
+            var s = await Task.Run(() =>
+            {
+                var secret = KeyVaultSecrets.GetOrAdd(clientID, (x) =>
+                {
+                    try
+                    {
+                        var sts = Enum.Parse<CoreServiceClient>(location, true);
+                        var scrtetstring = sts.GetDescriptionText().Split(",");
+                        //TODO 之後驗證端點用KnownAuthorityHosts取代,此SDK版本無支援
+                        var secret = new ClientSecretCredential(scrtetstring[0], scrtetstring[1], scrtetstring[2], new TokenCredentialOptions() { AuthorityHost = new Uri(scrtetstring[3]) });
+                        var client = new SecretClient(new Uri(((KeyVaultEndpoint)sts).GetDescriptionText()), secret);
+                        var clientSecret = client.GetSecretAsync(clientID).ConfigureAwait(false);
+                        return clientSecret.GetAwaiter().GetResult();
+                    }
+                    catch
+                    {
+                        return null;
+                    }
+                });
+                return secret;
+            });
+            return s;
+        }
+
+        public static bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
+        {
+            return true;
+            //if (expires != null)
+            //{
+            //    if (DateTime.UtcNow < expires)
+            //    {
+            //        return true;
+            //    }
+            //}
+
+            //return false;
+        }
+
+        private enum STSEndpoint
+        {
+            [Description("https://login.chinacloudapi.cn/4807e9cf-87b8-4174-aa5b-e76497d7392b")]
+            China,
+            [Description("https://login.microsoftonline.com/73a2bcc5-fe99-4566-aa8a-07e7bb287df1")]
+            Global
+        }
+
+        private enum STSScope
+        {
+            [Description("api://72643704-b2e7-4b26-b881-bd5865e7a7a5/.default")]
+            China,
+            [Description("api://8768b06f-c5c5-4b0c-abfb-d7ded354626d/.default")]
+            Global
+        }
+
+        private enum KeyVaultEndpoint
+        {
+            [Description("https://corekeyvaultcn.vault.azure.cn/")]
+            China,
+            [Description("https://corekeyvaultjp.vault.azure.net/")]
+            Global
+        }
+
+        private enum CoreServiceClient
+        {
+            [Description("4807e9cf-87b8-4174-aa5b-e76497d7392b,72643704-b2e7-4b26-b881-bd5865e7a7a5,tRYbDXtotEOe2Bbmo=[3h9Hbu_Trt:c6,https://login.partner.microsoftonline.cn")]
+            China,
+            [Description("73a2bcc5-fe99-4566-aa8a-07e7bb287df1,8768b06f-c5c5-4b0c-abfb-d7ded354626d,7=O./yws0L89WcEsece:9/4deJHP4E=F,https://login.microsoftonline.com/")]
+            Global
+        }
+    }
+}

+ 2 - 2
TEAMModelOS.SDK/Extension/JwtAuthExtension.cs

@@ -81,11 +81,11 @@ namespace TEAMModelOS.SDK.Extension
                 var handler = new JwtSecurityTokenHandler();
                 var validationParameters = new TokenValidationParameters
                 {
-                    RequireExpirationTime = true,
+                    RequireExpirationTime = false,
                     ValidateIssuer = false,
                     ValidateAudience = false,
                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt)),
-                    //ValidateLifetime = false,
+                    ValidateLifetime = false,
                     //LifetimeValidator = LifetimeValidator,
                     ClockSkew = TimeSpan.Zero
                 };

+ 72 - 1
TEAMModelOS.SDK/Models/Cosmos/Api/OpenApi.cs

@@ -28,22 +28,93 @@ namespace TEAMModelOS.SDK.Models
 
             PartitionKey = "IES5-API";
         } 
+        /// <summary>
+        /// 接口名称
+        /// </summary>
         public string name { get; set; }
+        /// <summary>
+        /// 接口url
+        /// </summary>
         public string url { get; set; }
+        /// <summary>
+        /// 请求方法
+        /// </summary>
         public string method { get; set; }
+        /// <summary>
+        /// 开放的api接口
+        /// </summary>
         public string descr { get; set; }
         public int auth { get; set; }
-
+        /// <summary>
+        /// r,w,d,l
+        /// </summary>
+        public string type { get; set; }
     }
+    [TableName(Name = "OpenApi")]
+    public class Webhook : TableEntity
+    {
+        public Webhook()
+        {
 
+            PartitionKey = "IES5-WEBHOOK";
+        }
+        /// <summary>
+        /// 接口名称
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 接口url
+        /// </summary>
+        public string url { get; set; }
+        /// <summary>
+        /// 请求方法
+        /// </summary>
+        public string method { get; set; }
+        /// <summary>
+        /// 开放的api接口
+        /// </summary>
+        public string descr { get; set; }
+        public int auth { get; set; }
+        /// <summary>
+        /// r,w,d,l
+        /// </summary>
+        public string type { get; set; }
+    }
     public class OpenApp : CosmosEntity {
+        /// <summary>
+        /// 图标
+        /// </summary>
         public string icon { get; set; }
+        /// <summary>
+        /// 应用名称
+        /// </summary>
         public string name { get; set; }
+        /// <summary>
+        /// 应用描述
+        /// </summary>
         public string descr { get; set; }
+        /// <summary>
+        /// 授权信息
+        /// </summary>
         public List<int> auths { get; set; } = new List<int>();
+        public List<int> webhooks { get; set; } = new List<int>();
+        /// <summary>
+        /// 学校编码
+        /// </summary>
         public string school { get; set; }
+        /// <summary>
+        /// 生成的token
+        /// </summary>
         public string token { get; set; }
         /// <summary>
+        /// domain的域名
+        /// </summary>
+        public string domain { get; set; }
+        /// <summary>
+        ///webhook
+        /// </summary>
+        public string webhookToken { get; set; }
+        /// <summary>
         /// 0禁用,1正常,2 token封禁
         /// </summary>
         public int status { get; set; }

+ 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; }
+
     }
 }

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

@@ -10,14 +10,26 @@ 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; }
-    }
+        /// <summary>
+        /// 课纲章节id
+        /// </summary>
+        public string  id { get; set; }
+        /// <summary>
+        /// 册别的id
+        /// </summary>
+        public string volumeId { get; set; }
+        /// <summary>
+        /// 校本课纲时传入 学校编码,私人课纲时传入醍摩豆ID
+        /// </summary>
+        public string codeval { get; set; }
+        public string scope { get; set; }
+        public  List<SyllabusTree>  trees  { get; set; }
 
+        public List<SyllabusAuth> auth { get; set; } = new List<SyllabusAuth>();
+    }
 }

+ 61 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Scoring.cs

@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.Common
+{
+    public class Scoring : CosmosEntity
+    {
+        public Scoring()
+        {
+            pk = "Scoring";
+        }
+        public string stuId { get; set; }
+        public string examId { get; set; }
+        public string subjectId { get; set; }
+        public List<Item> items { get; set; } = new List<Item>();
+        public string blob { get; set; }
+        public List<string> tIds { get; set; } = new List<string>();
+        public List<string> marks { get; set; } = new List<string>();
+        public List<double> scores { get; set; } = new List<double>();
+    }
+
+    public class Item
+    {
+        public List<Info> scores { get; set; } = new List<Info>();
+        //原题的配分
+        public double ssc { get; set; }
+        //public string tmdId { get; set; }
+        public bool flag
+        {
+            get
+            {
+                if (scores.Count > 2)
+                {
+                    //List<double> sc = scores.Select(s => s.sc).ToList();
+                    double diff = Math.Abs(scores.Select(s => s.sc).ToList().Aggregate((i, j) => (i - j) * 6));
+                    if (diff > ssc)
+                    {
+                        return false;
+                    }
+                    else {
+                        return true;
+                    }
+                    
+                }
+                else
+                {
+                    return true;
+                }
+
+            }
+        }
+
+    }
+    public class Info { 
+        public double sc { get; set; }
+        public string tmdId { get; set; }
+    }
+
+}

+ 3 - 1
TEAMModelOS.SDK/Models/Cosmos/Common/Snode.cs

@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.Text;
+using System.Text.Json;
 
 namespace TEAMModelOS.SDK.Models.Cosmos.Common
 {
@@ -63,6 +64,7 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
         /// <summary>
         /// 存放地址 外部链接是绝对地址有http   blob是相对地址
         /// </summary>
-        public List<string> link { get; set; }
+        public string link { get; set; }
+       
     }
 }

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

@@ -20,5 +20,27 @@ namespace TEAMModelOS.SDK.Models
         [Required(ErrorMessage = "{0} 必须填写")]
         public List<Tnode> children { get; set; }
         public string volumeId { get; set; }
+        public string codeval { get; set; }
+        public List<SyllabusAuth> auth { get; set; } = new List<SyllabusAuth>();
+        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; }
+        /// <summary>
+        /// 分享  type=coedit共编,share分享
+        /// </summary>
+        public string type { get; set; }
+        /// <summary>
+        /// 是否同意
+        /// </summary>
+        public int agree { get; set; } = 0;
     }
+     
 }

+ 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; }
+    }
+}

+ 4 - 17
TEAMModelOS.SDK/Models/Cosmos/Common/Volume.cs

@@ -74,7 +74,7 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
         /// <summary>
         /// 学校编码
         /// </summary>
-        [Required(ErrorMessage = "school 必须设置")]
+       // [Required(ErrorMessage = "school 必须设置")]
         public string school { get; set; }
        // public bool repeat { get; set; }
         /// <summary>
@@ -82,22 +82,9 @@ 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>();
+        public List<string> syllabusIds { get; set; } = new List<string>();
+
     }
+
 }

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/Common/Vote.cs

@@ -27,7 +27,7 @@ namespace TEAMModelOS.SDK.Models
         /// <summary>
         /// 学校编码或教师tmdid
         /// </summary>
-        [Required(ErrorMessage = "school 必须设置")]
+       // [Required(ErrorMessage = "school 必须设置")]
         public string school { get; set; }
         /// <summary>
         /// 投票名称

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/School/Class.cs

@@ -41,7 +41,7 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public string periodId { get; set; }
         /// <summary>
-        /// 年级
+        /// 年级 此字段再入学年的情况下已经无用,现阶段只是用来处理历史数据
         /// </summary>
         public string gradeId { get; set; }
         //入学年

+ 1 - 0
TEAMModelOS.SDK/Models/Cosmos/School/Paper.cs

@@ -62,6 +62,7 @@ namespace TEAMModelOS.SDK.Models
         public int multipleRule { get; set; }
         //记录试卷大小
         public long? size { get; set; } = 0;
+        
         /// <summary>
         /// type:{
         ///     pointkey:[num1,num2....]

+ 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>
+        /// 册别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>
+        /// 分享  type=coedit共编,share分享
+        /// </summary>
+        public string type { get; set; }
+        /// <summary>
+        /// 是否同意
+        /// </summary>
+        public int agree { get; set; } = 0;
+    }
+    /// <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>
+        /// 课纲章节的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; }
+
+        /// <summary>
+        /// 分享  type=coedit共编,share分享
+        /// </summary>
+        public string type { get; set; }
+        /// <summary>
+        /// 是否同意
+        /// </summary>
+        public int agree { get; set; } = 0;
+    }
+}

+ 77 - 0
TEAMModelOS.SDK/Models/Service/NotificationService.cs

@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Json;
+using System.Text;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Extension;
+
+namespace TEAMModelOS.SDK.Models.Service
+{
+    public class NotificationService
+    {
+        private readonly HttpClient _httpClient;
+        public NotificationService(HttpClient httpClient)
+        {
+            _httpClient = httpClient;
+        }
+        public    async Task<int> SendNotification(string clientID, string clientSecret, string location, string url, Notification notification) {
+            if (location.Contains("China")) {
+                location = "China";
+            }
+            else if (location.Contains("Global"))
+            {
+                location = "Global";
+            }
+            var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
+            _httpClient.DefaultRequestHeaders.Add("Authorization",$"Bearer {token.AccessToken}" );
+            HttpResponseMessage responseMessage = await _httpClient.PostAsJsonAsync(url, notification);
+            if (responseMessage.StatusCode == HttpStatusCode.OK)
+            {
+                return 200;
+            }
+            else if (responseMessage.StatusCode == HttpStatusCode.Unauthorized)
+            {
+                return 401;
+            }
+            else {
+                return 500;
+            }
+        }
+    }
+
+    public class Notification {
+        /// <summary>
+        /// App name (hita) 小寫
+        /// </summary>
+        public string hubName { get; set; }
+        /// <summary>
+        /// 通知訊息種類,分為msg,info及notice。       
+        /// msg : 一般訊息,會存Redis,拿了就刪。
+        /// info : 公告訊息或給多人讀取的訊息,會存Redis,拿了不刪,只能等時間到期或透過API刪除。
+        /// notice : 屬於系統層級訊息,不存Redis,直接裸送訊息。
+        /// </summary>
+        public string type { get; set; }
+        /// <summary>
+        /// 送訊息的來源端 格式為"{服務}:{類別}: ..." 如"ies5:hbrd","ies5:hbrd:hb0901"
+        /// </summary>
+        public string from { get; set; }
+        /// <summary>
+        /// 接收對象或手機註冊的tag,ID或服務等...
+        /// </summary>
+        public List<string> to { get; set; }
+        /// <summary>
+        /// 	標題。
+        /// </summary>
+        public string label { get; set; }
+        /// <summary>
+        /// 正文。
+        /// </summary>
+        public string body { get; set; }
+        /// <summary>
+        /// 該訊息到期時間(UTC),單位為秒,且必須大於現在時間。
+        /// </summary>
+        public long expires { get; set; }
+    }
+}

+ 14 - 0
TEAMModelOS.SDK/Models/Table/tmdInfo.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models.Table
+{
+
+    public class tmdInfo
+    {
+        public string tmdId { get; set; }
+        public List<double> tScore { get; set; } = new List<double>();
+        public string mark { get; set; }
+    }
+}

+ 4 - 0
TEAMModelOS.SDK/TEAMModelOS.SDK.csproj

@@ -13,15 +13,19 @@
   <ItemGroup>
     <PackageReference Include="AspectCore.Extensions.Reflection" Version="2.2.0" />
     <PackageReference Include="Azure.Cosmos" Version="4.0.0-preview3" />
+    <PackageReference Include="Azure.Identity" Version="1.4.0" />
     <PackageReference Include="Azure.Messaging.ServiceBus" Version="7.1.1" />
+    <PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.1.0" />
     <PackageReference Include="Azure.Storage.Blobs.Batch" Version="12.5.1" />
     <PackageReference Include="Azure.Storage.Queues" Version="12.6.1" />
     <PackageReference Include="ClouDASLibx" Version="1.2.7" />
     <PackageReference Include="DocumentFormat.OpenXml" Version="2.12.3" />
     <PackageReference Include="HtmlAgilityPack" Version="1.11.32" />
+    <PackageReference Include="Lib.AspNetCore.ServerSentEvents" Version="6.0.0" />
     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.10" />
     <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
     <PackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="5.0.4" />
+    <PackageReference Include="Microsoft.Identity.Client" Version="4.32.1" />
     <PackageReference Include="StackExchange.Redis" Version="2.2.4" />
     <PackageReference Include="SvgNet" Version="2.1.1" />
     <PackageReference Include="System.Drawing.Common" Version="5.0.2" />

+ 7 - 1
TEAMModelOS.sln

@@ -11,7 +11,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TEAMModelGrpc", "TEAMModelG
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TEAMModelFunction", "TEAMModelFunction\TEAMModelFunction.csproj", "{78470113-6261-4F9A-9EF3-E315F060813D}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TEAMModelAPI", "TEAMModelAPI\TEAMModelAPI.csproj", "{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TEAMModelAPI", "TEAMModelAPI\TEAMModelAPI.csproj", "{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{E1A7F6EA-319E-4582-A800-A04DEB8284D9}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -39,6 +41,10 @@ Global
 		{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{2146FEEC-7178-4141-A8C7-CBEBAEE404A6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{E1A7F6EA-319E-4582-A800-A04DEB8284D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{E1A7F6EA-319E-4582-A800-A04DEB8284D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E1A7F6EA-319E-4582-A800-A04DEB8284D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{E1A7F6EA-319E-4582-A800-A04DEB8284D9}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 2 - 0
TEAMModelOS/ClientApp/package.json

@@ -33,6 +33,8 @@
 		"firebase": "^7.19.0",
 		"firestore": "^1.1.6",
 		"html2canvas": "^1.0.0-rc.7",
+		"html2pdf.js": "^0.9.3",
+		"i18next": "^20.3.1",
 		"imports-loader": "^0.8.0",
 		"increase-memory-limit": "^1.0.7",
 		"js-sha1": "^0.6.0",

文件差异内容过多而无法显示
+ 14827 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.js


文件差异内容过多而无法显示
+ 1 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.js.map


文件差异内容过多而无法显示
+ 313 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.sandbox.js


文件差异内容过多而无法显示
+ 1 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.sandbox.js.map


文件差异内容过多而无法显示
+ 65293 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.worker.js


文件差异内容过多而无法显示
+ 1 - 0
TEAMModelOS/ClientApp/public/pdfBuild/pdf.worker.js.map


+ 1 - 1
TEAMModelOS/ClientApp/public/web/viewer.html

@@ -34,7 +34,7 @@ See https://github.com/adobe-type-tools/cmap-resources
 
 <!-- This snippet is used in production (included from viewer.html) -->
 <link rel="resource" type="application/l10n" href="locale/locale.properties">
-<script src="../build/pdf.js"></script>
+<script src="../pdfBuild/pdf.js"></script>
 
 
   <script src="viewer.js"></script>

+ 5 - 5
TEAMModelOS/ClientApp/public/web/viewer.js

@@ -206,7 +206,7 @@ const defaultOptions = {
     kind: OptionKind.WORKER
   },
   workerSrc: {
-    value: "../build/pdf.worker.js",
+    value: "../pdfBuild/pdf.worker.js",
     kind: OptionKind.WORKER
   }
 };
@@ -220,7 +220,7 @@ const defaultOptions = {
     kind: OptionKind.VIEWER
   };
   defaultOptions.sandboxBundleSrc = {
-    value: "../build/pdf.sandbox.js",
+    value: "../pdfBuild/pdf.sandbox.js",
     kind: OptionKind.VIEWER
   };
 }
@@ -3921,10 +3921,10 @@ function apiPageModeToSidebarView(mode) {
 
 let pdfjsLib;
 
-if (typeof window !== "undefined" && window["pdfjs-dist/build/pdf"]) {
-  pdfjsLib = window["pdfjs-dist/build/pdf"];
+if (typeof window !== "undefined" && window["pdfjs-dist/pdfBuild/pdf"]) {
+  pdfjsLib = window["pdfjs-dist/pdfBuild/pdf"];
 } else {
-  pdfjsLib = require("../build/pdf.js");
+  pdfjsLib = require("../pdfBuild/pdf.js");
 }
 
 module.exports = pdfjsLib;

文件差异内容过多而无法显示
+ 1 - 1
TEAMModelOS/ClientApp/public/web/viewer.js.map


+ 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)
     }
 }

+ 7 - 0
TEAMModelOS/ClientApp/src/api/evaluation.js

@@ -0,0 +1,7 @@
+import { fetch, post } from '@/api/http'
+
+export default {
+    getFilterCount: function (data) {        
+        return post('/item/cond-count', data)
+    }
+}

+ 2 - 0
TEAMModelOS/ClientApp/src/api/index.js

@@ -29,6 +29,7 @@ import spaceAuth from './spaceAuth'
 import room from './room'
 import mark from './mark'
 import openMgmt from './openMgmt';
+import service from './service';
 
 export default {
     accessToken,
@@ -59,6 +60,7 @@ export default {
     room,
     mark,
     openMgmt,
+	service,
 
     // 获取登录跳转链接
     getLoginLink: function (data) {

+ 8 - 1
TEAMModelOS/ClientApp/src/api/openMgmt.js

@@ -20,7 +20,7 @@ export default{
      * @param {} data
      */
     getApiList: function (data) {
-        return post('/open-api/get', data)
+        return post('/open-api/get-api', data)
     },
     /**
      * 新增/编辑
@@ -43,5 +43,12 @@ export default{
      */
     delOpen: function (data) {
         return post('/open-api/delete-app', data)
+    },
+    /**
+     * 获取订阅通知
+     * @param {} data
+     */
+     getWebhook: function (data) {
+        return post('/open-api/get-webhook', 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)
+    },
 }

+ 23 - 0
TEAMModelOS/ClientApp/src/api/service.js

@@ -0,0 +1,23 @@
+import { fetch, post } from '@/api/http'
+export default {
+	/* 获取端外通知 */
+    getNotification: function (data) {
+        return post('https://api2.teammodel.net/service/getnotification', data)
+    },
+    /* 获取id详细信息 */
+    getIdProfile: function (host,data) {
+        return post(`${host}/oauth2/profile`, data)
+    },
+    /* 发送短信验证码 */
+    sandMsgCode: function (host,data) {
+        return post(`${host}/service/sandsms/pin`, data)
+    },
+    /* 发送邮件验证码 */
+    sandMailCode: function (host,data) {
+        return post(`${host}/service/sandmail/pin`, data)
+    },
+    /* 裝置或服務取得金鑰及刷新金鑰 */
+    getToken: function (host,data) {
+        return post(`${host}/oauth2/token`, data)
+    },
+}

+ 5 - 0
TEAMModelOS/ClientApp/src/api/studentWeb.js

@@ -225,4 +225,9 @@ export default {
 	isAnswerd: function (data) {
 	    return post('/common/survey/answered',data)
 	},
+
+    // 删除不存在的投票和问卷
+    delActivity: function (data) {
+        return post("/common/delete-activity", data)
+    }
 }

+ 15 - 0
TEAMModelOS/ClientApp/src/api/syllabus.js

@@ -19,6 +19,21 @@ export default {
 	DeleteTree:function(data) {
 	    return post('/common/syllabus/delete', data)
 	},
+	ShareTree:function(data) {
+	    return post('/teacher/share/to', data)
+	},
+	FindShare:function(data) {
+	    return post('/teacher/share/find', data)
+	},
+	ViewShare:function(data) {
+	    return post('/teacher/share/view-share', data)
+	},
+	ShareAgree:function(data) {
+	    return post('/teacher/share/agree-share', data)
+	},
+	CheckLink:function(data) {
+	    return post('/common/syllabus/check-link', data)
+	},
 	// 查找知识块数量
 	FindBlockCount: function (data) {
 		return post('/knowledges/find-count', data)

+ 164 - 3
TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html

@@ -54,6 +54,48 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe6c3;</span>
+                <div class="name">开放</div>
+                <div class="code-name">&amp;#xe6c3;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe718;</span>
+                <div class="name">在籍学生</div>
+                <div class="code-name">&amp;#xe718;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe633;</span>
+                <div class="name">icon_icon_ 学生管理</div>
+                <div class="code-name">&amp;#xe633;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe637;</span>
+                <div class="name">教师</div>
+                <div class="code-name">&amp;#xe637;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe630;</span>
+                <div class="name">学生</div>
+                <div class="code-name">&amp;#xe630;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe659;</span>
+                <div class="name">微信 (1)</div>
+                <div class="code-name">&amp;#xe659;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe643;</span>
+                <div class="name">地球</div>
+                <div class="code-name">&amp;#xe643;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe603;</span>
                 <div class="name">手机未认证</div>
@@ -774,9 +816,9 @@
 <pre><code class="language-css"
 >@font-face {
   font-family: 'iconfont';
-  src: url('iconfont.woff2?t=1621999720250') format('woff2'),
-       url('iconfont.woff?t=1621999720250') format('woff'),
-       url('iconfont.ttf?t=1621999720250') format('truetype');
+  src: url('iconfont.woff2?t=1624327216353') format('woff2'),
+       url('iconfont.woff?t=1624327216353') format('woff'),
+       url('iconfont.ttf?t=1624327216353') format('truetype');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -802,6 +844,69 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont icon-open"></span>
+            <div class="name">
+              开放
+            </div>
+            <div class="code-name">.icon-open
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-student1"></span>
+            <div class="name">
+              在籍学生
+            </div>
+            <div class="code-name">.icon-student1
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-student2"></span>
+            <div class="name">
+              icon_icon_ 学生管理
+            </div>
+            <div class="code-name">.icon-student2
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-teacher"></span>
+            <div class="name">
+              教师
+            </div>
+            <div class="code-name">.icon-teacher
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-student"></span>
+            <div class="name">
+              学生
+            </div>
+            <div class="code-name">.icon-student
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-wechat"></span>
+            <div class="name">
+              微信 (1)
+            </div>
+            <div class="code-name">.icon-wechat
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-earth"></span>
+            <div class="name">
+              地球
+            </div>
+            <div class="code-name">.icon-earth
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont icon-phone-unverify"></span>
             <div class="name">
@@ -1882,6 +1987,62 @@
       <div class="content symbol">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-open"></use>
+                </svg>
+                <div class="name">开放</div>
+                <div class="code-name">#icon-open</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-student1"></use>
+                </svg>
+                <div class="name">在籍学生</div>
+                <div class="code-name">#icon-student1</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-student2"></use>
+                </svg>
+                <div class="name">icon_icon_ 学生管理</div>
+                <div class="code-name">#icon-student2</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-teacher"></use>
+                </svg>
+                <div class="name">教师</div>
+                <div class="code-name">#icon-teacher</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-student"></use>
+                </svg>
+                <div class="name">学生</div>
+                <div class="code-name">#icon-student</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-wechat"></use>
+                </svg>
+                <div class="name">微信 (1)</div>
+                <div class="code-name">#icon-wechat</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-earth"></use>
+                </svg>
+                <div class="name">地球</div>
+                <div class="code-name">#icon-earth</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#icon-phone-unverify"></use>

+ 31 - 3
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 2000444 */
-  src: url('iconfont.woff2?t=1621999720250') format('woff2'),
-       url('iconfont.woff?t=1621999720250') format('woff'),
-       url('iconfont.ttf?t=1621999720250') format('truetype');
+  src: url('iconfont.woff2?t=1624327216353') format('woff2'),
+       url('iconfont.woff?t=1624327216353') format('woff'),
+       url('iconfont.ttf?t=1624327216353') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,34 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-open:before {
+  content: "\e6c3";
+}
+
+.icon-student1:before {
+  content: "\e718";
+}
+
+.icon-student2:before {
+  content: "\e633";
+}
+
+.icon-teacher:before {
+  content: "\e637";
+}
+
+.icon-student:before {
+  content: "\e630";
+}
+
+.icon-wechat:before {
+  content: "\e659";
+}
+
+.icon-earth:before {
+  content: "\e643";
+}
+
 .icon-phone-unverify:before {
   content: "\e603";
 }

文件差异内容过多而无法显示
+ 1 - 1
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js


+ 49 - 0
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json

@@ -5,6 +5,55 @@
   "css_prefix_text": "icon-",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "20587121",
+      "name": "开放",
+      "font_class": "open",
+      "unicode": "e6c3",
+      "unicode_decimal": 59075
+    },
+    {
+      "icon_id": "8827519",
+      "name": "在籍学生",
+      "font_class": "student1",
+      "unicode": "e718",
+      "unicode_decimal": 59160
+    },
+    {
+      "icon_id": "19109549",
+      "name": "icon_icon_ 学生管理",
+      "font_class": "student2",
+      "unicode": "e633",
+      "unicode_decimal": 58931
+    },
+    {
+      "icon_id": "8156489",
+      "name": "教师",
+      "font_class": "teacher",
+      "unicode": "e637",
+      "unicode_decimal": 58935
+    },
+    {
+      "icon_id": "3904398",
+      "name": "学生",
+      "font_class": "student",
+      "unicode": "e630",
+      "unicode_decimal": 58928
+    },
+    {
+      "icon_id": "1382584",
+      "name": "微信 (1)",
+      "font_class": "wechat",
+      "unicode": "e659",
+      "unicode_decimal": 58969
+    },
+    {
+      "icon_id": "2678587",
+      "name": "地球",
+      "font_class": "earth",
+      "unicode": "e643",
+      "unicode_decimal": 58947
+    },
     {
       "icon_id": "21777109",
       "name": "手机未认证",

二进制
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf


二进制
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff


二进制
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2


二进制
TEAMModelOS/ClientApp/src/assets/image/1-1.jpg


二进制
TEAMModelOS/ClientApp/src/assets/login/1-1.jpg


二进制
TEAMModelOS/ClientApp/src/assets/login/1-2.png


二进制
TEAMModelOS/ClientApp/src/assets/login/1-3.png


二进制
TEAMModelOS/ClientApp/src/assets/login/1-4.png


二进制
TEAMModelOS/ClientApp/src/assets/login/1-5.png


二进制
TEAMModelOS/ClientApp/src/assets/login/1-7.png


二进制
TEAMModelOS/ClientApp/src/assets/login/2-1.png


二进制
TEAMModelOS/ClientApp/src/assets/login/2-2.jpg


二进制
TEAMModelOS/ClientApp/src/assets/login/3-1.jpg


二进制
TEAMModelOS/ClientApp/src/assets/login/3-2.png


文件差异内容过多而无法显示
+ 1 - 0
TEAMModelOS/ClientApp/src/assets/login/icon_student.svg


文件差异内容过多而无法显示
+ 1 - 0
TEAMModelOS/ClientApp/src/assets/login/icon_teacher.svg


文件差异内容过多而无法显示
+ 1 - 0
TEAMModelOS/ClientApp/src/assets/login/ies5_logo_2.svg


二进制
TEAMModelOS/ClientApp/src/assets/login/login_bg.jpg


+ 54 - 0
TEAMModelOS/ClientApp/src/assets/mark/0.svg

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFB300;}
+	.st1{fill:#4A6DFB;}
+	.st2{fill:#FBEC6D;}
+	.st3{fill:#FA7D15;}
+	.st4{fill:#2746E0;}
+	.st5{fill:#FFDD2E;}
+	.st6{fill:#B1C1FF;}
+	.st7{fill:#7999FF;}
+	.st8{fill:none;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st9{fill:#FFFFFF;}
+	.st10{fill:none;}
+	.st11{fill:#FFB300;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st12{fill:#4A6DFB;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st13{fill:#FBEC6D;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st14{fill:#FA7D15;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st15{fill:#2746E0;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st16{fill:#FFDD2E;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st17{fill:#B1C1FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st18{fill:#7999FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st19{fill:#FFFFFF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+</style>
+<g id="图层_1">
+</g>
+<g id="图层_2">
+	<g>
+		<polygon class="st0" points="833.28,590.14 635.35,787.28 620.58,801.99 501.47,683.35 714.17,471.5 		"/>
+		<path class="st3" d="M370.34,693.63L88.72,413.14L412.74,90.42l342.03,340.66L491.16,693.63
+			C457.79,726.85,403.7,726.85,370.34,693.63z"/>
+		<path class="st0" d="M921.61,243.59c0,13.16-5.04,26.32-15.12,36.35L695.46,490.15l-60.11-59.87l-65.82-65.55l65.82-65.55
+			l92.32-91.94c49.39-49.19,129.45-49.19,178.83,0C916.57,217.27,921.61,230.44,921.61,243.59z"/>
+		<path class="st3" d="M921.61,243.59c0,13.16-5.04,26.32-15.12,36.35L695.46,490.15l-60.11-59.87v-131.1l92.32-91.94
+			c49.39-49.19,129.45-49.19,178.83,0C916.57,217.27,921.61,230.44,921.61,243.59z"/>
+		<path class="st2" d="M728.53,457.2L491.15,693.63c-33.36,33.23-87.45,33.23-120.81,0c-82.23-81.9-82.23-214.69,0-296.59
+			c41.12-40.96,95-61.43,148.9-61.43c40.5,0,81.03,11.57,116.11,34.72c11.59,7.64,22.58,16.54,32.78,26.71L728.53,457.2z"/>
+		<path class="st5" d="M385.03,275.88l-76.82-76.51c-29.53-29.42-29.53-77.11,0-106.53l0,0c29.53-29.42,77.42-29.42,106.95,0
+			l76.82,76.51c29.53,29.42,29.53,77.11,0,106.53l0,0C462.45,305.29,414.57,305.29,385.03,275.88z"/>
+		<path class="st5" d="M276.5,383.97l-76.82-76.51c-29.53-29.42-29.53-77.11,0-106.53l0,0c29.53-29.42,77.42-29.42,106.95,0
+			l76.82,76.51c29.53,29.42,29.53,77.11,0,106.53l0,0C353.92,413.39,306.04,413.39,276.5,383.97z"/>
+		<path class="st5" d="M167.97,492.07l-76.82-76.51c-29.53-29.42-29.53-77.11,0-106.53l0,0c29.53-29.42,77.42-29.42,106.95,0
+			l76.82,76.51c29.53,29.42,29.53,77.11,0,106.53l0,0C245.39,521.48,197.51,521.48,167.97,492.07z"/>
+		<polygon class="st3" points="833.28,590.14 635.35,787.28 635.35,550.01 714.17,471.5 		"/>
+		<polygon class="st1" points="955,630.5 635.35,948.87 630.98,953.23 482.44,805.27 635.35,652.98 806.45,482.56 		"/>
+		<polygon class="st4" points="955,630.5 635.35,948.87 635.35,652.98 806.45,482.56 		"/>
+		<path class="st5" d="M728.53,457.2l-93.19,92.81V370.33c11.59,7.64,22.58,16.54,32.78,26.71L728.53,457.2z"/>
+		<ellipse class="st3" cx="834.99" cy="617.4" rx="49.43" ry="49.23"/>
+		<ellipse class="st3" cx="741.47" cy="710.54" rx="49.43" ry="49.23"/>
+	</g>
+</g>
+</svg>

+ 47 - 0
TEAMModelOS/ClientApp/src/assets/mark/1.svg

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFB300;}
+	.st1{fill:#4A6DFB;}
+	.st2{fill:#FBEC6D;}
+	.st3{fill:#FA7D15;}
+	.st4{fill:#2746E0;}
+	.st5{fill:#FFDD2E;}
+	.st6{fill:#B1C1FF;}
+	.st7{fill:#7999FF;}
+	.st8{fill:none;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st9{fill:#FFFFFF;}
+	.st10{fill:none;}
+	.st11{fill:#FFB300;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st12{fill:#4A6DFB;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st13{fill:#FBEC6D;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st14{fill:#FA7D15;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st15{fill:#2746E0;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st16{fill:#FFDD2E;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st17{fill:#B1C1FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st18{fill:#7999FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st19{fill:#FFFFFF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+</style>
+<g id="图层_1">
+</g>
+<g id="图层_2">
+	<g>
+		<path class="st0" d="M850.73,854.26V955H173.27V854.26c0-65.03,53.02-117.72,118.41-117.72h440.63
+			C797.71,736.54,850.73,789.24,850.73,854.26z"/>
+		<rect x="389.74" y="363.91" class="st1" width="244.52" height="372.63"/>
+		<path class="st6" d="M389.74,628.94h-0.28c-51.87,0-93.93-42.05-93.93-93.93v-77.17c0-51.87,42.05-93.93,93.93-93.93h0.28V628.94z
+			"/>
+		<path class="st7" d="M634.54,628.94h-0.27V363.91h0.27c51.87,0,93.93,42.05,93.93,93.93v77.17
+			C728.46,586.89,686.41,628.94,634.54,628.94z"/>
+		<ellipse class="st0" cx="512" cy="199.6" rx="131.36" ry="130.6"/>
+		<polygon class="st1" points="566.14,777.34 566.14,914.2 459.25,914.2 459.25,860.04 429.8,860.04 429.8,823.44 476.91,777.34 		
+			"/>
+		<path class="st3" d="M850.73,854.26V955H512V736.54h220.32C797.71,736.54,850.73,789.24,850.73,854.26z"/>
+		<rect x="512" y="777.34" class="st4" width="54.14" height="136.86"/>
+		<rect x="512" y="363.91" class="st4" width="122.26" height="372.63"/>
+		<path class="st3" d="M643.36,199.6c0,72.13-58.81,130.6-131.36,130.6V69C584.55,69,643.36,127.47,643.36,199.6z"/>
+	</g>
+</g>
+</svg>

+ 57 - 0
TEAMModelOS/ClientApp/src/assets/mark/2.svg

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFB300;}
+	.st1{fill:#4A6DFB;}
+	.st2{fill:#FBEC6D;}
+	.st3{fill:#FA7D15;}
+	.st4{fill:#2746E0;}
+	.st5{fill:#FFDD2E;}
+	.st6{fill:#B1C1FF;}
+	.st7{fill:#7999FF;}
+	.st8{fill:none;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st9{fill:#FFFFFF;}
+	.st10{fill:none;}
+	.st11{fill:#FFB300;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st12{fill:#4A6DFB;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st13{fill:#FBEC6D;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st14{fill:#FA7D15;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st15{fill:#2746E0;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st16{fill:#FFDD2E;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st17{fill:#B1C1FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st18{fill:#7999FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st19{fill:#FFFFFF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+</style>
+<g id="图层_1">
+</g>
+<g id="图层_2">
+	<g>
+		<polygon class="st0" points="578.56,845.59 445.44,845.59 474.93,574.8 549.07,574.8 		"/>
+		<polygon class="st3" points="578.56,845.59 510.59,845.59 510.59,574.8 549.07,574.8 		"/>
+		<path class="st3" d="M318.64,482.85h-86.28c-73.58,0-133.45-59.56-133.45-132.77c0-54.14,44.27-98.18,98.68-98.18h121.05
+			c22.05,0,39.92,17.78,39.92,39.72v151.52C358.55,465.07,340.68,482.85,318.64,482.85z M197.58,331.33
+			c-10.39,0-18.84,8.41-18.84,18.74c0,29.41,24.05,53.34,53.61,53.34h46.36v-72.08H197.58z"/>
+		<path class="st3" d="M665.45,443.13V291.62c0-21.94,17.87-39.72,39.92-39.72h121.05c54.41,0,98.68,44.04,98.68,98.18
+			c0,73.21-59.86,132.77-133.45,132.77h-86.28C683.32,482.85,665.45,465.07,665.45,443.13z M745.28,331.33v72.08h46.36
+			c29.56,0,53.61-23.93,53.61-53.34c0-10.33-8.45-18.74-18.84-18.74H745.28z"/>
+		<path class="st2" d="M749.8,224.68v161c0,130.67-106.47,236.6-237.8,236.6h-1.41c-130.68-0.77-236.39-106.4-236.39-236.6v-161
+			H749.8z"/>
+		<path class="st0" d="M827.13,146.85c0,21.49-8.76,40.95-22.91,55.03c-14.16,14.08-33.71,22.8-55.31,22.8H275.1
+			c-43.21,0-78.23-34.84-78.23-77.83c0-21.49,8.76-40.95,22.91-55.05C233.94,77.71,253.5,69,275.1,69h473.8
+			C792.11,69,827.13,103.86,827.13,146.85z"/>
+		<polygon class="st1" points="561.86,393.46 573.64,461.74 512,429.51 510.59,430.24 450.36,461.74 462.14,393.46 412.27,345.1 
+			481.18,335.14 510.59,275.86 512,273.01 542.82,335.14 611.73,345.1 		"/>
+		<polygon class="st4" points="561.86,393.46 573.64,461.74 512,429.51 512,273.01 542.82,335.14 611.73,345.1 		"/>
+		<path class="st3" d="M827.13,146.85c0,21.49-8.76,40.95-22.91,55.03c-14.16,14.08-33.71,22.8-55.31,22.8H510.59V69H748.9
+			C792.11,69,827.13,103.86,827.13,146.85z"/>
+		<path class="st5" d="M749.8,224.68v161c0,130.67-106.47,236.6-237.8,236.6h-1.41v-397.6H749.8z"/>
+		<path class="st2" d="M694.81,955H329.19c0-30.21,12.3-57.57,32.2-77.36c19.91-19.81,47.39-32.05,77.76-32.05h145.71
+			C645.58,845.59,694.81,894.57,694.81,955z"/>
+		<path class="st5" d="M694.81,955H510.59V845.59h74.27C645.58,845.59,694.81,894.57,694.81,955z"/>
+		<polygon class="st4" points="561.86,393.46 573.64,461.74 512,429.51 510.59,430.24 510.59,275.86 512,273.01 542.82,335.14 
+			611.73,345.1 		"/>
+	</g>
+</g>
+</svg>

+ 51 - 0
TEAMModelOS/ClientApp/src/assets/mark/3.svg

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFB300;}
+	.st1{fill:#4A6DFB;}
+	.st2{fill:#FBEC6D;}
+	.st3{fill:#FA7D15;}
+	.st4{fill:#2746E0;}
+	.st5{fill:#FFDD2E;}
+	.st6{fill:#B1C1FF;}
+	.st7{fill:#7999FF;}
+	.st8{fill:none;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st9{fill:#FFFFFF;}
+	.st10{fill:none;}
+	.st11{fill:#FFB300;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st12{fill:#4A6DFB;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st13{fill:#FBEC6D;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st14{fill:#FA7D15;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st15{fill:#2746E0;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st16{fill:#FFDD2E;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st17{fill:#B1C1FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st18{fill:#7999FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st19{fill:#FFFFFF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+</style>
+<g id="图层_1">
+</g>
+<g id="图层_2">
+	<g>
+		<path class="st0" d="M863.84,430.19v490.27c0,19.08-15.5,34.54-34.62,34.54H194.79c-19.12,0-34.62-15.46-34.62-34.54V430.19
+			H863.84z"/>
+		<path class="st1" d="M357.23,69c-56.53,0-102.34,45.71-102.34,102.1c0,28.2,11.45,53.71,29.97,72.19s44.11,29.91,72.37,29.91
+			h102.34V171.1C459.57,114.71,413.75,69,357.23,69z M388.52,202.32h-31.3c-17.26,0-31.29-14.01-31.29-31.22
+			c0-17.21,14.03-31.22,31.29-31.22c17.25,0,31.3,14.01,31.3,31.22V202.32z"/>
+		<path class="st4" d="M564.43,171.1v102.1h102.34c28.26,0,53.85-11.43,72.37-29.91s29.97-43.99,29.97-72.19
+			c0-56.38-45.81-102.1-102.34-102.1C610.26,69,564.43,114.71,564.43,171.1z M635.48,171.1c0-17.21,14.04-31.22,31.3-31.22
+			c17.26,0,31.29,14.01,31.29,31.22c0,17.21-14.03,31.22-31.29,31.22h-31.3V171.1z"/>
+		<path class="st3" d="M863.84,430.19v490.27c0,19.08-15.5,34.54-34.62,34.54H512V430.19H863.84z"/>
+		<path class="st2" d="M892.6,309.09v121.1H131.4v-121.1c0-19.82,16.12-35.9,35.98-35.9h689.23
+			C876.48,273.19,892.6,289.27,892.6,309.09z"/>
+		<path class="st5" d="M892.6,309.09v121.1H512v-157h344.61C876.48,273.19,892.6,289.27,892.6,309.09z"/>
+		<rect x="459.57" y="273.19" class="st6" width="104.86" height="157"/>
+		<rect x="459.57" y="430.19" class="st1" width="104.86" height="524.81"/>
+		<rect x="160.16" y="581.23" class="st6" width="703.67" height="104.61"/>
+		<rect x="512" y="430.19" class="st4" width="52.43" height="524.81"/>
+		<rect x="512" y="273.19" class="st7" width="52.43" height="157"/>
+		<rect x="512" y="581.23" class="st7" width="351.84" height="104.61"/>
+	</g>
+</g>
+</svg>

+ 63 - 0
TEAMModelOS/ClientApp/src/assets/mark/4.svg

@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFB300;}
+	.st1{fill:#4A6DFB;}
+	.st2{fill:#FBEC6D;}
+	.st3{fill:#FA7D15;}
+	.st4{fill:#2746E0;}
+	.st5{fill:#FFDD2E;}
+	.st6{fill:#B1C1FF;}
+	.st7{fill:#7999FF;}
+	.st8{fill:none;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st9{fill:#FFFFFF;}
+	.st10{fill:none;}
+	.st11{fill:#FFB300;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st12{fill:#4A6DFB;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st13{fill:#FBEC6D;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st14{fill:#FA7D15;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st15{fill:#2746E0;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st16{fill:#FFDD2E;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st17{fill:#B1C1FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st18{fill:#7999FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st19{fill:#FFFFFF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+</style>
+<g id="图层_1">
+</g>
+<g id="图层_2">
+	<g>
+		<polygon class="st0" points="559.21,330.91 955,723.6 732.07,944.65 336.28,551.95 		"/>
+		<polygon class="st3" points="492.81,396.75 888.59,789.45 798.47,878.8 402.69,486.11 		"/>
+		<polygon class="st6" points="464.22,330.84 69,722.97 292.25,944.33 687.47,552.2 		"/>
+		<polygon class="st7" points="530.72,396.78 135.5,788.91 225.75,878.39 620.97,486.26 		"/>
+		<g>
+			<g>
+				<path class="st2" d="M515.71,419.53c0,0,7.63,154.93-37.63,199.8s-118.63,44.87-163.89,0s-45.26-117.62,0-162.49
+					S515.71,419.53,515.71,419.53z"/>
+				<path class="st5" d="M515.71,419.53c0,0,156.26-7.56,201.52,37.31s45.26,117.62,0,162.49s-118.63,44.87-163.89,0
+					S515.71,419.53,515.71,419.53z"/>
+				<path class="st5" d="M515.71,419.53c0,0-7.63-154.93,37.63-199.8s118.63-44.87,163.89,0s45.26,117.62,0,162.49
+					S515.71,419.53,515.71,419.53z"/>
+				<path class="st2" d="M515.71,419.53c0,0-156.26,7.56-201.52-37.31s-45.26-117.62,0-162.49s118.63-44.87,163.89,0
+					S515.71,419.53,515.71,419.53z"/>
+			</g>
+			<path class="st0" d="M515.71,419.53c0,0-126.54,138.33-203.59,138.33s-139.52-61.93-139.52-138.33S235.06,281.2,312.12,281.2
+				S515.71,419.53,515.71,419.53z"/>
+			<path class="st0" d="M655.22,621.39c0,76.4-62.45,138.33-139.51,138.33h-0.5c-76.85-0.27-139.02-62.11-139.02-138.33
+				c0-73.73,129.97-193.18,139.02-201.4c0.33-0.31,0.5-0.46,0.5-0.46S655.22,544.99,655.22,621.39z"/>
+			<path class="st3" d="M515.71,419.53c0,0,126.54-138.33,203.59-138.33s139.52,61.93,139.52,138.33S796.36,557.86,719.3,557.86
+				S515.71,419.53,515.71,419.53z"/>
+			<path class="st0" d="M655.22,217.69c0,76.4-139.51,201.84-139.51,201.84s-0.17-0.15-0.5-0.46
+				c-9.05-8.22-139.02-127.65-139.02-201.38c0-76.24,62.18-138.06,139.02-138.33h0.5C592.77,79.35,655.22,141.27,655.22,217.69z"/>
+			<path class="st3" d="M655.22,621.39c0,76.4-62.45,138.33-139.51,138.33h-0.5V419.99c0.33-0.31,0.5-0.46,0.5-0.46
+				S655.22,544.99,655.22,621.39z"/>
+			<path class="st3" d="M655.22,217.69c0,76.4-139.51,201.84-139.51,201.84s-0.17-0.15-0.5-0.46V79.35h0.5
+				C592.77,79.35,655.22,141.27,655.22,217.69z"/>
+			<ellipse class="st5" cx="515.22" cy="419.07" rx="107.05" ry="106.13"/>
+			<ellipse class="st1" cx="515.22" cy="419.07" rx="58.15" ry="57.65"/>
+		</g>
+	</g>
+</g>
+</svg>

+ 94 - 0
TEAMModelOS/ClientApp/src/assets/mark/5.svg

@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFB300;}
+	.st1{fill:#4A6DFB;}
+	.st2{fill:#FBEC6D;}
+	.st3{fill:#FA7D15;}
+	.st4{fill:#2746E0;}
+	.st5{fill:#FFDD2E;}
+	.st6{fill:#B1C1FF;}
+	.st7{fill:#7999FF;}
+	.st8{fill:none;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st9{fill:#FFFFFF;}
+	.st10{fill:none;}
+	.st11{fill:#FFB300;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st12{fill:#4A6DFB;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st13{fill:#FBEC6D;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st14{fill:#FA7D15;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st15{fill:#2746E0;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st16{fill:#FFDD2E;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st17{fill:#B1C1FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st18{fill:#7999FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st19{fill:#FFFFFF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+</style>
+<g id="图层_1">
+</g>
+<g id="图层_2">
+	<g>
+		<g>
+			<path class="st1" d="M644.91,389.7c-4.15,4.02-6.04,9.83-5.04,15.52l22.44,127.87c2.51,14.27-12.48,25.17-25.25,18.38
+				L522.6,490.57c-2.54-1.35-5.34-2.03-8.14-2.03c-2.79,0-5.6,0.67-8.15,2.03l-114.47,60.89c-12.77,6.8-27.75-4.11-25.25-18.38
+				l22.44-127.87c1-5.69-0.88-11.5-5.03-15.52l-93.19-90.23c-10.4-10.07-4.67-27.71,9.64-29.74L428.8,251.6
+				c5.71-0.8,10.65-4.4,13.18-9.59l56.87-116.66c3.18-6.51,9.39-9.76,15.61-9.76c6.22,0,12.42,3.26,15.6,9.76l56.87,116.66
+				c2.53,5.19,7.47,8.78,13.18,9.59l128.33,18.13c14.32,2.02,20.04,19.67,9.64,29.74L644.91,389.7z"/>
+			<polygon class="st6" points="603.62,382.43 625.06,507.71 514.46,449.39 512.86,448.56 400.66,507.71 422.1,382.43 
+				331.33,293.68 456.76,275.4 512.86,161.41 514.46,164.65 568.96,275.4 694.39,293.68 			"/>
+			<path class="st4" d="M644.91,389.7c-4.15,4.02-6.04,9.83-5.04,15.52l22.44,127.87c2.51,14.27-12.48,25.17-25.25,18.38
+				L522.6,490.57c-2.54-1.35-5.34-2.03-8.14-2.03V115.58c6.22,0,12.42,3.26,15.6,9.76l56.87,116.66c2.53,5.19,7.47,8.78,13.18,9.59
+				l128.33,18.13c14.32,2.02,20.04,19.67,9.64,29.74L644.91,389.7z"/>
+			<polygon class="st7" points="603.62,382.43 625.06,507.71 514.46,449.39 514.46,164.65 568.96,275.4 694.39,293.68 			"/>
+			<polygon class="st0" points="546.12,355.64 553.84,399.62 514.46,378.68 475.08,399.62 482.8,355.64 450.74,324.59 
+				494.89,318.36 514.46,278.22 534.02,318.36 578.17,324.59 			"/>
+			<polygon class="st3" points="546.12,355.64 553.84,399.62 514.46,378.68 514.46,278.22 534.02,318.36 578.17,324.59 			"/>
+		</g>
+		<g>
+			<path class="st8" d="M512,774.68c-188.27,0-340.9-152.88-340.9-341.48c0-89.41,34.31-170.8,90.45-231.67"/>
+			<path class="st0" d="M256.31,383.43c-20.56,18.43-47.99,24.29-72.91,18.1c-3.41-25.48,5.43-52.16,26-70.6
+				c20.57-18.44,48.01-24.3,72.92-18.09C285.72,338.34,276.87,365,256.31,383.43z"/>
+			<path class="st0" d="M157.51,323.47c14.55,23.49,15.55,51.56,5.13,75.07c-25.64-1.06-50.33-14.42-64.89-37.91
+				c-14.56-23.49-15.55-51.58-5.12-75.07C118.29,286.63,142.96,299.98,157.51,323.47z"/>
+			<path class="st0" d="M252.87,482.35c-15.39,22.94-40.53,35.39-66.21,35.54c-9.58-23.85-7.57-51.89,7.83-74.84
+				c15.4-22.95,40.55-35.4,66.22-35.53C270.27,431.39,268.26,459.41,252.87,482.35z"/>
+			<path class="st0" d="M142.36,448.62c19.88,19.17,27.76,46.13,23.44,71.49c-25.11,5.3-52.33-1.55-72.22-20.72
+				c-19.89-19.18-27.76-46.15-23.43-71.49C95.28,422.61,122.48,429.46,142.36,448.62z"/>
+			<path class="st0" d="M288.47,569.42c-6.59,26.84-25.93,47.18-50,56.16c-17.17-19.11-24.9-46.13-18.31-72.98
+				c6.59-26.85,25.95-47.2,50.01-56.15C287.34,515.57,295.06,542.57,288.47,569.42z"/>
+			<path class="st0" d="M173.12,575.76c25.25,11.16,41.88,33.77,46.53,59.07c-21.77,13.62-49.67,16.55-74.93,5.39
+				c-25.26-11.17-41.9-33.79-46.52-59.08C119.98,567.53,147.88,564.6,173.12,575.76z"/>
+			<path class="st0" d="M360.2,642.76c1.49,27.6-11.1,52.7-31.52,68.3c-21.98-13.27-37.22-36.87-38.71-64.49
+				c-1.49-27.61,11.11-52.72,31.53-68.3C343.48,591.57,358.71,615.16,360.2,642.76z"/>
+			<path class="st0" d="M251.69,682.45c27.4,3.32,49.88,20.1,61.67,42.95c-16.87,19.38-42.72,30.31-70.12,26.99
+				c-27.41-3.32-49.91-20.12-61.67-42.96C198.46,690.06,224.29,679.13,251.69,682.45z"/>
+			<path class="st0" d="M256.11,271.1c-14.36,23.6-38.93,37.16-64.57,38.44c-10.62-23.4-9.86-51.5,4.51-75.11
+				c14.37-23.61,38.95-37.17,64.58-38.44C271.24,219.42,270.47,247.5,256.11,271.1z"/>
+			<path class="st8" d="M512,774.68c188.27,0,340.9-152.88,340.9-341.48c0-89.41-34.31-170.8-90.45-231.67"/>
+			<path class="st3" d="M767.69,383.43c20.56,18.43,47.99,24.29,72.91,18.1c3.41-25.48-5.43-52.16-26-70.6
+				c-20.57-18.44-48.01-24.3-72.92-18.09C738.28,338.34,747.13,365,767.69,383.43z"/>
+			<path class="st3" d="M866.49,323.47c-14.55,23.49-15.55,51.56-5.13,75.07c25.64-1.06,50.33-14.42,64.89-37.91
+				c14.56-23.49,15.55-51.58,5.12-75.07C905.71,286.63,881.04,299.98,866.49,323.47z"/>
+			<path class="st3" d="M771.13,482.35c15.39,22.94,40.53,35.39,66.21,35.54c9.58-23.85,7.57-51.89-7.83-74.84
+				c-15.4-22.95-40.55-35.4-66.22-35.53C753.73,431.39,755.74,459.41,771.13,482.35z"/>
+			<path class="st3" d="M881.64,448.62c-19.88,19.17-27.76,46.13-23.44,71.49c25.11,5.3,52.33-1.55,72.22-20.72
+				c19.89-19.18,27.76-46.15,23.43-71.49C928.72,422.61,901.52,429.46,881.64,448.62z"/>
+			<path class="st3" d="M735.53,569.42c6.59,26.84,25.93,47.18,50,56.16c17.17-19.11,24.9-46.13,18.31-72.98
+				c-6.59-26.85-25.95-47.2-50.01-56.15C736.66,515.57,728.94,542.57,735.53,569.42z"/>
+			<path class="st3" d="M850.88,575.76c-25.25,11.16-41.88,33.77-46.53,59.07c21.77,13.62,49.67,16.55,74.93,5.39
+				c25.26-11.17,41.9-33.79,46.52-59.08C904.02,567.53,876.12,564.6,850.88,575.76z"/>
+			<path class="st3" d="M663.8,642.76c-1.49,27.6,11.1,52.7,31.52,68.3c21.98-13.27,37.22-36.87,38.71-64.49
+				c1.49-27.61-11.11-52.72-31.53-68.3C680.52,591.57,665.29,615.16,663.8,642.76z"/>
+			<path class="st3" d="M772.31,682.45c-27.4,3.32-49.88,20.1-61.67,42.95c16.87,19.38,42.72,30.31,70.12,26.99
+				c27.41-3.32,49.91-20.12,61.67-42.96C825.54,690.06,799.71,679.13,772.31,682.45z"/>
+			<path class="st3" d="M767.89,271.1c14.36,23.6,38.93,37.16,64.57,38.44c10.62-23.4,9.86-51.5-4.51-75.11
+				C813.58,210.82,789,197.26,763.37,196C752.76,219.42,753.53,247.5,767.89,271.1z"/>
+			<ellipse class="st2" cx="510.25" cy="774.67" rx="133.53" ry="133.75"/>
+			<path class="st5" d="M643.78,774.67c0,73.87-59.78,133.75-133.53,133.75V640.91C583.99,640.91,643.78,700.8,643.78,774.67z"/>
+			<path class="st0" d="M570.55,774.67c0,33.36-26.99,60.4-60.3,60.4s-60.31-27.04-60.31-60.4c0-33.36,27-60.4,60.31-60.4
+				S570.55,741.31,570.55,774.67z"/>
+			<path class="st3" d="M570.55,774.67c0,33.36-26.99,60.4-60.3,60.4v-120.8C543.55,714.27,570.55,741.31,570.55,774.67z"/>
+		</g>
+	</g>
+</g>
+</svg>

+ 77 - 0
TEAMModelOS/ClientApp/src/assets/mark/6.svg

@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFB300;}
+	.st1{fill:#4A6DFB;}
+	.st2{fill:#FBEC6D;}
+	.st3{fill:#FA7D15;}
+	.st4{fill:#2746E0;}
+	.st5{fill:#FFDD2E;}
+	.st6{fill:#B1C1FF;}
+	.st7{fill:#7999FF;}
+	.st8{fill:none;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st9{fill:#FFFFFF;}
+	.st10{fill:none;}
+	.st11{fill:#FFB300;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st12{fill:#4A6DFB;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st13{fill:#FBEC6D;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st14{fill:#FA7D15;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st15{fill:#2746E0;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st16{fill:#FFDD2E;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st17{fill:#B1C1FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st18{fill:#7999FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st19{fill:#FFFFFF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+</style>
+<g id="图层_1">
+</g>
+<g id="图层_2">
+	<g>
+		<path class="st2" d="M690.41,548.08l-46.02,16.25c-14.57,5.15-21.46,21.79-14.79,35.73l20.97,43.81
+			c10.56,22.06-12.42,45.16-34.53,34.72l-44.79-21.14c-13.88-6.54-30.38,0.29-35.56,14.75l-16.61,46.41
+			c-4.35,12.15-15.5,17.86-26.25,17.15c-9.57-0.63-18.82-6.34-22.69-17.15l-16.61-46.41c-5.18-14.46-21.68-21.29-35.56-14.75
+			l-44.79,21.14c-22.11,10.44-45.09-12.66-34.53-34.72l20.97-43.81c6.67-13.94-0.22-30.58-14.79-35.73l-46.02-16.25
+			c-23.11-8.16-23.11-40.84,0-49l46.02-16.25c14.57-5.15,21.46-21.78,14.79-35.72l-20.97-43.82
+			c-10.56-22.05,12.42-45.16,34.53-34.72l44.79,21.14c13.88,6.55,30.38-0.29,35.56-14.74l16.61-46.41
+			c3.87-10.81,13.12-16.53,22.69-17.16c10.75-0.71,21.9,5.02,26.25,17.16l16.61,46.41c5.18,14.45,21.68,21.29,35.56,14.74
+			l44.79-21.14c22.11-10.44,45.09,12.67,34.53,34.72l-20.97,43.82c-6.67,13.94,0.22,30.57,14.79,35.72l46.02,16.25
+			C713.52,507.24,713.52,539.92,690.41,548.08z"/>
+		<path class="st0" d="M587.35,533.07l-0.78,0.75c-9.97,9.6-14.55,23.51-12.24,37.15l0.23,1.36c5.8,34.15-30.04,60.15-60.7,44.04
+			l-1.97-1.04c-5.96-3.13-12.51-4.74-19.05-4.8c-6.74-0.07-13.51,1.49-19.67,4.69l-1.97,1.03c-30.75,15.95-66.46-10.26-60.46-44.38
+			l0.23-1.35c2.4-13.63-2.11-27.56-12.02-37.22l-0.77-0.75c-24.92-24.25-11.1-66.54,23.32-71.4l1.59-0.23
+			c13.61-1.92,25.4-10.41,31.55-22.7l0.93-1.86c7.69-15.37,22.48-23.06,37.28-23.11c14.97-0.05,29.96,7.72,37.66,23.32l0.92,1.86
+			c6.08,12.33,17.83,20.88,31.43,22.88l1.58,0.23C598.81,466.6,612.39,508.96,587.35,533.07z"/>
+		<ellipse class="st4" cx="373.01" cy="899.53" rx="55.86" ry="55.47"/>
+		<ellipse class="st1" cx="347.63" cy="152.97" rx="55.86" ry="55.47"/>
+		<ellipse class="st1" cx="741.21" cy="102.97" rx="34.2" ry="33.97"/>
+		<ellipse class="st6" cx="182.17" cy="670.65" rx="34.2" ry="33.97"/>
+		<ellipse class="st3" cx="841.83" cy="645.65" rx="34.2" ry="33.97"/>
+		<ellipse class="st3" cx="592.27" cy="161.36" rx="34.2" ry="33.97"/>
+		<g>
+			<line class="st8" x1="715.55" y1="304.19" x2="807.62" y2="212.75"/>
+			<line class="st8" x1="181.61" y1="834.42" x2="273.69" y2="742.98"/>
+			<line class="st8" x1="715.55" y1="742.98" x2="807.62" y2="834.42"/>
+			<line class="st8" x1="181.61" y1="212.75" x2="273.69" y2="304.19"/>
+		</g>
+		<path class="st5" d="M690.41,548.08l-46.02,16.25c-14.57,5.15-21.46,21.79-14.79,35.73l20.97,43.81
+			c10.56,22.06-12.42,45.16-34.53,34.72l-44.79-21.14c-13.88-6.54-30.38,0.29-35.56,14.75l-16.61,46.41
+			c-4.35,12.15-15.5,17.86-26.25,17.15V311.4c10.75-0.71,21.9,5.02,26.25,17.16l16.61,46.41c5.18,14.45,21.68,21.29,35.56,14.74
+			l44.79-21.14c22.11-10.44,45.09,12.67,34.53,34.72l-20.97,43.82c-6.67,13.94,0.22,30.57,14.79,35.72l46.02,16.25
+			C713.52,507.24,713.52,539.92,690.41,548.08z"/>
+		<path class="st3" d="M587.35,533.07l-0.78,0.75c-9.97,9.6-14.55,23.51-12.24,37.15l0.23,1.36c5.8,34.15-30.04,60.15-60.7,44.04
+			l-1.97-1.04c-5.96-3.13-12.51-4.74-19.05-4.8V413.25c14.97-0.05,29.96,7.72,37.66,23.32l0.92,1.86
+			c6.08,12.33,17.83,20.88,31.43,22.88l1.58,0.23C598.81,466.6,612.39,508.96,587.35,533.07z"/>
+		<path class="st3" d="M630.72,772.48l7.47,17.13c1.54,3.54,5.21,5.65,9.04,5.22l18.57-2.1c7.63-0.86,12.61,7.78,8.06,13.95
+			l-11.1,15.03c-2.29,3.1-2.29,7.34,0,10.44l11.1,15.03c4.56,6.17-0.43,14.81-8.06,13.95l-18.57-2.1c-3.83-0.43-7.5,1.68-9.04,5.22
+			l-7.47,17.13c-3.07,7.03-13.04,7.03-16.11,0l-7.47-17.13c-1.54-3.54-5.21-5.65-9.04-5.22l-18.57,2.1
+			c-7.63,0.86-12.61-7.78-8.06-13.95l11.1-15.03c2.29-3.1,2.29-7.34,0-10.44l-11.1-15.03c-4.56-6.17,0.43-14.81,8.06-13.95
+			l18.57,2.1c3.83,0.43,7.5-1.68,9.04-5.22l7.47-17.13C617.68,765.45,627.66,765.45,630.72,772.48z"/>
+		<path class="st0" d="M224.43,338.16l7.47,17.13c1.54,3.54,5.21,5.65,9.04,5.22l18.57-2.1c7.63-0.86,12.61,7.78,8.06,13.95
+			l-11.1,15.03c-2.29,3.1-2.29,7.34,0,10.44l11.1,15.03c4.56,6.17-0.43,14.81-8.06,13.95l-18.57-2.1c-3.83-0.43-7.5,1.68-9.04,5.22
+			l-7.47,17.13c-3.07,7.03-13.04,7.03-16.11,0l-7.47-17.13c-1.54-3.54-5.21-5.65-9.04-5.22l-18.57,2.1
+			c-7.63,0.86-12.61-7.78-8.06-13.95l11.1-15.03c2.29-3.1,2.29-7.34,0-10.44l-11.1-15.03c-4.56-6.17,0.43-14.81,8.06-13.95
+			l18.57,2.1c3.83,0.43,7.5-1.68,9.04-5.22l7.47-17.13C211.39,331.13,221.37,331.13,224.43,338.16z"/>
+	</g>
+</g>
+</svg>

+ 62 - 0
TEAMModelOS/ClientApp/src/assets/mark/7.svg

@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFB300;}
+	.st1{fill:#4A6DFB;}
+	.st2{fill:#FBEC6D;}
+	.st3{fill:#FA7D15;}
+	.st4{fill:#2746E0;}
+	.st5{fill:#FFDD2E;}
+	.st6{fill:#B1C1FF;}
+	.st7{fill:#7999FF;}
+	.st8{fill:none;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st9{fill:#FFFFFF;}
+	.st10{fill:none;}
+	.st11{fill:#FFB300;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st12{fill:#4A6DFB;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st13{fill:#FBEC6D;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st14{fill:#FA7D15;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st15{fill:#2746E0;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st16{fill:#FFDD2E;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st17{fill:#B1C1FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st18{fill:#7999FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st19{fill:#FFFFFF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+</style>
+<g id="图层_1">
+</g>
+<g id="图层_2">
+	<g>
+		<polygon class="st0" points="619.2,737.25 404.8,737.25 467.66,430.27 556.34,430.27 		"/>
+		<path class="st1" d="M695.79,797.31v74.05H328.21v-74.05c0-33.17,26.95-60.06,60.22-60.06h247.14
+			C668.84,737.25,695.79,764.14,695.79,797.31z"/>
+		<path class="st0" d="M723.74,895.87V955H300.26v-59.13c0-13.54,11-24.51,24.57-24.51h374.32
+			C712.73,871.36,723.74,882.33,723.74,895.87z"/>
+		<path class="st3" d="M723.74,895.87V955H511.28v-83.64h187.88C712.73,871.36,723.74,882.33,723.74,895.87z"/>
+		<path class="st4" d="M695.79,797.31v74.05H511.28V737.25h124.29C668.84,737.25,695.79,764.14,695.79,797.31z"/>
+		<polygon class="st3" points="619.2,737.25 511.28,737.25 511.28,430.27 556.34,430.27 		"/>
+		<g>
+			<path class="st1" d="M660.62,380.46c-4.73,4.57-6.88,11.17-5.74,17.63l25.56,145.29c2.86,16.21-14.21,28.6-28.76,20.88
+				l-130.4-69.19c-2.9-1.54-6.08-2.31-9.27-2.31c-3.18,0-6.38,0.76-9.28,2.31l-130.41,69.19c-14.55,7.72-31.62-4.67-28.76-20.88
+				l25.56-145.29c1.14-6.46-1.01-13.07-5.73-17.63L257.23,277.94c-11.84-11.44-5.33-31.49,10.99-33.79l146.21-20.6
+				c6.5-0.91,12.13-5,15.01-10.89l64.79-132.56C497.84,72.7,504.92,69,512,69c7.09,0,14.15,3.7,17.78,11.09l64.79,132.56
+				c2.88,5.89,8.51,9.98,15.02,10.89l146.2,20.6c16.31,2.3,22.83,22.35,10.99,33.79L660.62,380.46z"/>
+			<polygon class="st6" points="613.58,372.2 638.01,514.56 512,448.29 510.18,447.35 382.36,514.56 406.78,372.2 303.38,271.36 
+				446.27,250.59 510.18,121.07 512,124.76 574.09,250.59 716.98,271.36 			"/>
+			<path class="st4" d="M660.62,380.46c-4.73,4.57-6.88,11.17-5.74,17.63l25.56,145.29c2.86,16.21-14.21,28.6-28.76,20.88
+				l-130.4-69.19c-2.9-1.54-6.08-2.31-9.27-2.31V69c7.09,0,14.15,3.7,17.78,11.09l64.79,132.56c2.88,5.89,8.51,9.98,15.02,10.89
+				l146.2,20.6c16.31,2.3,22.83,22.35,10.99,33.79L660.62,380.46z"/>
+			<polygon class="st7" points="613.58,372.2 638.01,514.56 512,448.29 512,124.76 574.09,250.59 716.98,271.36 			"/>
+			<polygon class="st0" points="548.07,341.77 556.86,391.74 512,367.94 467.14,391.74 475.93,341.77 439.42,306.49 489.71,299.41 
+				512,253.8 534.29,299.41 584.58,306.49 			"/>
+			<polygon class="st3" points="548.07,341.77 556.86,391.74 512,367.94 512,253.8 534.29,299.41 584.58,306.49 			"/>
+		</g>
+		<path class="st0" d="M601.49,806.45c0,6.32-2.57,12.04-6.73,16.19c-4.16,4.15-9.9,6.72-16.25,6.72H445.49
+			c-12.69,0-22.98-10.26-22.98-22.91c0-6.33,2.57-12.06,6.73-16.2c4.16-4.15,9.9-6.72,16.25-6.72h133.02
+			C591.2,783.53,601.49,793.79,601.49,806.45z"/>
+		<path class="st3" d="M601.49,806.45c0,6.32-2.57,12.04-6.73,16.19c-4.16,4.15-9.9,6.72-16.25,6.72h-68.33v-45.82h68.33
+			C591.2,783.53,601.49,793.79,601.49,806.45z"/>
+	</g>
+</g>
+</svg>

+ 54 - 0
TEAMModelOS/ClientApp/src/assets/mark/8.svg

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
+<style type="text/css">
+	.st0{fill:#FFB300;}
+	.st1{fill:#4A6DFB;}
+	.st2{fill:#FBEC6D;}
+	.st3{fill:#FA7D15;}
+	.st4{fill:#2746E0;}
+	.st5{fill:#FFDD2E;}
+	.st6{fill:#B1C1FF;}
+	.st7{fill:#7999FF;}
+	.st8{fill:none;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st9{fill:#FFFFFF;}
+	.st10{fill:none;}
+	.st11{fill:#FFB300;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st12{fill:#4A6DFB;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st13{fill:#FBEC6D;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st14{fill:#FA7D15;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st15{fill:#2746E0;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st16{fill:#FFDD2E;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st17{fill:#B1C1FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st18{fill:#7999FF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+	.st19{fill:#FFFFFF;stroke:#3E3A39;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
+</style>
+<g id="图层_1">
+</g>
+<g id="图层_2">
+	<g>
+		<rect x="222.43" y="180.69" class="st12" width="580.76" height="215.05"/>
+		<rect x="222.43" y="244.75" class="st13" width="580.76" height="86.94"/>
+		<polygon class="st12" points="479.66,743.94 69,332.75 220.87,180.69 631.54,591.87 		"/>
+		<polygon class="st13" points="524.9,698.64 114.24,287.46 175.63,225.98 586.3,637.17 		"/>
+		<rect x="512.81" y="180.69" class="st15" width="290.38" height="215.05"/>
+		<rect x="512.81" y="244.75" class="st16" width="290.38" height="86.94"/>
+		<polygon class="st12" points="544.34,743.94 955,332.75 803.13,180.69 392.46,591.87 		"/>
+		<polygon class="st11" points="499.1,698.64 909.76,287.46 848.37,225.98 437.7,637.17 		"/>
+		<path class="st13" d="M722.02,633.03c0,115.87-93.59,209.84-209.21,210.28c-0.27,0.01-0.54,0.01-0.81,0.01
+			c-115.99,0-210.02-94.14-210.02-210.29c0-116.14,94.03-210.28,210.02-210.28c0.27,0,0.54,0,0.81,0.01
+			C628.43,423.19,722.02,517.16,722.02,633.03z"/>
+		<path class="st11" d="M653.76,633.03c0,78.12-63.02,141.5-140.94,141.95H512c-78.29,0-141.76-63.55-141.76-141.95
+			c0-78.38,63.46-141.94,141.76-141.94h0.81C590.74,491.53,653.76,554.91,653.76,633.03z"/>
+		<polygon class="st12" points="604.43,665.75 540.57,675.04 512.81,731.34 512,732.99 483.43,675.04 419.57,665.75 465.78,620.64 
+			454.87,556.96 512,587.02 512.81,586.6 569.13,556.96 558.22,620.64 		"/>
+		<polygon class="st17" points="558.22,657.36 569.13,721.05 512.81,691.4 512,690.98 454.87,721.05 465.78,657.36 419.57,612.25 
+			483.43,602.96 512,545.01 512.81,546.66 540.57,602.96 604.43,612.25 		"/>
+		<path class="st16" d="M722.02,633.03c0,115.87-93.59,209.84-209.21,210.28V422.76C628.43,423.19,722.02,517.16,722.02,633.03z"/>
+		<path class="st14" d="M653.76,633.03c0,78.12-63.02,141.5-140.94,141.95V491.09C590.74,491.53,653.76,554.91,653.76,633.03z"/>
+		<polygon class="st15" points="604.43,665.75 540.57,675.04 512.81,731.34 512.81,586.6 569.13,556.96 558.22,620.64 		"/>
+		<polygon class="st18" points="558.22,657.36 569.13,721.05 512.81,691.4 512.81,546.66 540.57,602.96 604.43,612.25 		"/>
+	</g>
+</g>
+</svg>

二进制
TEAMModelOS/ClientApp/src/assets/mark/img0.jpg


二进制
TEAMModelOS/ClientApp/src/assets/mark/img1.jpg


二进制
TEAMModelOS/ClientApp/src/assets/mark/img2.jpg


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


部分文件因为文件数量过多而无法显示