liqk преди 5 години
родител
ревизия
751d8a9b03

+ 7 - 0
TEAMModelOS.Service/Models/Core/Student.cs

@@ -10,6 +10,13 @@ namespace TEAMModelOS.Service.Models.Core
     [CosmosDB(RU = 400, Name = "CoreStudent")]
     public class Student
     {
+   public Student()
+    {
+      password = new Password();
+      productToken = new List<ProductToken>();
+      oauth = new List<Oauth>();
+      classroom = new Classroom();
+    }
         public string id { get; set; }
         /// <summary>
         /// 0 动态id  透過第三方申請,未認證手機號,TEAMModelId暫時為virtualId但是不顯示在介面上,當使用者驗證手機號後TEAMModelId會變為手機號。

+ 1 - 0
TEAMModelOS/ClientApp/package.json

@@ -17,6 +17,7 @@
     "d3": "^5.9.2",
     "echarts": "^4.2.1",
     "element-ui": "^2.12.0",
+    "js-sha1": "^0.6.0",
     "json-markup": "^1.1.3",
     "jsonpath": "^1.0.2",
     "jwt-decode": "^2.2.0",

+ 2 - 5
TEAMModelOS/ClientApp/src/api/uploadFile.js

@@ -3,11 +3,8 @@ export default {
     getBlobSAS: function (data) {
         return post('/api/File/getBlobSAS', data);
     },
-    createSharedAccess: function (data) {
-        return post('/api/File/CreateSharedAccessPolicy', data);
-    },
-    deleteSharedAccess: function (data) {
-        return post('/api/File/DeleteSharedAccessPolicyAsync', data);
+    getContainerSAS: function (data) {
+        return post('/api/File/getContainerSAS', data);
     }
 
 }

+ 256 - 38
TEAMModelOS/ClientApp/src/common/UploadFile.vue

@@ -1,52 +1,270 @@
 <template>
-    <div>
-        <Upload type="drag" :action="uploadUrl" multiple :on-success="getFileUrl" :before-upload="beforeUpload" class="upload-wrap">
-            <p style="margin:20px 0px; margin-top:100px;font-size:30px;">点击或者拖拽上传</p>
-            <Icon type="ios-cloud-upload" size="80" style="margin-bottom:100px;" />
-        </Upload>
+  <div>
+    <Upload type="drag" action="" multiple :before-upload="beforeUpload" class="upload-wrap">
+      <p style="margin:20px 0px; margin-top:80px;font-size:30px;">点击或者拖拽上传</p>
+      <Icon type="ios-cloud-upload" size="80" style="margin-bottom:80px;" />
+    </Upload>
+    <div class="upload-file-box">
+      <div class="upload-file-item" v-for="(item,index) in uploadedList">
+        <Icon type="ios-folder" />
+        <p class="upload-file-name">{{item.fileName}}</p>
+        <img width="25" style="float:right;" src="@/assets/loading/loading3.svg" v-if="item.status == 0"/>
+        <Icon type="md-checkmark" style="float:right;" color="aqua" size="20" v-else-if="item.status == 1"/>
+        <Icon type="md-close" style="float:right;" color="red" size="20" v-else-if="item.status == 2"/>
+      </div>
     </div>
+  </div>
 </template>
 <script>
-    export default {
-        data() {
-            return {
+  require('@/utils/azure-storage-blob.js')
+  import sha1 from 'js-sha1'
+  export default {
+    data() {
+      return {
+        containerURL: undefined,
+        sasString: '',
+        uploadedList: [],
+        contentTypes: [
+          ['JPG', 'JPEG', 'PNG', 'GIF'],
+          ['AVI', 'MP4'],
+          ['PPT', 'PPTX', 'DOC', 'DOCX', 'PDF', 'XLS', 'XLSX', 'HTE', 'HETX']
+        ],
+      }
+    },
+    props: {
+      accountName: {
+        default: 'teammodelostest',
+        type: String
+      },
+      containerName: {
+        default: 'teammodelos',
+        type: String
+      },
+      pathName: {
+        default: '',
+        type: String
+      },
 
+    },
+    methods: {
+      checkSize() {
+
+      },
+      initBlob() {
+        this.containerURL = new window.azblob.ContainerURL(
+          `https://${this.accountName}.blob.core.chinacloudapi.cn/${this.containerName + this.pathName}?${this.sasString}`,
+          window.azblob.StorageURL.newPipeline(new window.azblob.AnonymousCredential())
+        )
+      },
+      dataURLtoFile(dataurl, filename) {
+        var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
+          bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
+        while (n--) {
+          u8arr[n] = bstr.charCodeAt(n);
+        }
+        return new File([u8arr], filename, { type: mime });
+      },
+      compressFile(file,fileInfo) {
+        let reader = new FileReader()
+        reader.readAsDataURL(file)
+        reader.onload = (e) => {
+          let dataUrl = e.target.result
+          let img = new Image()
+          img.src = dataUrl
+          img.onload = () => {
+            let canvas = document.createElement('canvas')
+            let ctx = canvas.getContext('2d')
+            ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
+            let newImgData = canvas.toDataURL(file.type, 0.2)
+            var resultFile = this.dataURLtoFile(newImgData, file.name)
+            this.initBlob()
+            const compressBlobURL = window.azblob.BlockBlobURL.fromContainerURL(
+              this.containerURL,
+              'compress' + file.name
+            )
+            window.azblob.uploadBrowserDataToBlockBlob(
+              window.azblob.Aborter.none,
+              resultFile,
+              compressBlobURL
+            ).then(
+              res => {
+                fileInfo['compressUrl'] = `https://${this.accountName}.blob.core.chinacloudapi.cn/${this.containerName + this.pathName}/compress${file.name}`
+                console.log(fileInfo)
+                this.$emit("successData", fileInfo)
+              },
+              err => {
+                fileInfo['status'] = 2
+                console.log(err)
+              }
+            )
+          }
+        }
+      },
+      uploadToBlob(file) {
+        const blockBlobURL = window.azblob.BlockBlobURL.fromContainerURL(
+          this.containerURL,
+          file.name
+        )
+        let fileItem = {}
+        fileItem['fileName'] = file.name
+        fileItem['blobUrl'] = `https://${this.accountName}.blob.core.chinacloudapi.cn/${this.containerName + this.pathName}/${file.name}`
+        fileItem['extension'] = file.name.substring(file.name.lastIndexOf('.') + 1)
+        fileItem['size'] = file.size
+        fileItem['status'] = 0
+        fileItem['contentType'] = file.type
+        let type = 'other';
+        for (let item in this.contentTypes) {
+          if (this.contentTypes[item].indexOf(fileItem.extension.toUpperCase()) !== -1) {
+            switch (true) {
+              case item == 0:
+                type = 'picture'
+                break
+              case item == 1:
+                type = 'video'
+                break
+              case item == 2:
+                type = 'document'
+                break
+              default:
+                break
             }
-        },
-        props: {
-            uploadUrl: {
-                default: '',
-                type: String
+            break
+          }
+        }
+        fileItem['type'] = type
+        this.uploadedList.push(fileItem)
+        window.azblob.uploadBrowserDataToBlockBlob(
+          window.azblob.Aborter.none,
+          file,
+          blockBlobURL
+        ).then(
+          res => {
+            let reader = new FileReader()
+            reader.readAsArrayBuffer(file)
+            //reader.readAsArrayBuffer(file)
+            reader.onload = (ev) => {
+              try {
+                let fileRes = ev.target.result
+                let str = sha1(fileRes)
+                console.log(str)
+                let index = this.getIndex(this.uploadedList, fileItem)
+                this.uploadedList[index].status = 1
+                this.uploadedList[index]['createTime'] = Date.parse(res.lastModified)
+                this.uploadedList[index]['sha1Code'] = str
+                if (this.uploadedList[index].type == 'picture' || this.uploadedList[index].type == 'video') {
+                  console.log(this.uploadedList[index])
+                  this.compressFile(file,this.uploadedList[index])
+                } else {
+                  this.$emit("successData", this.uploadedList[index])
+                }
+              } catch (e) {
+                console.log(e)
+              }
             }
-        },
-        methods: {
-            checkSize() {
-
-            },
-            getFileUrl() {
-
-            },
-            beforeUpload(file) {
-                this.$api.uploadFile.getBlobSAS().then(
-                    (res) => {
-
-                    },
-                    (err) => {
-
-                    }
-                )
+            
+          },
+          err => {
+            fileItem['status'] = 2
+            console.log(err)
+          }
+        )
+        return false
+      },
+      beforeUpload(file) {
+        console.log(file)
+        let url =  file.name
+        this.$api.uploadFile.getContainerSAS().then(
+          (res) => {
+            if (res.error == null) {
+              this.sasString = res.result.data
+              this.initBlob()
+              this.uploadToBlob(file)
+            } else {
+              alert("API error!")
             }
-        },
-        mounted() {
-
-        },
-        created() {
-
+          },
+          (err) => {
+            alert("API error!")
+          }
+        )
+        return false
+      },
+      canvasDataURL(path, obj) {
+        var img = new Image()
+        img.src = path
+        img.onload = function () {
+          var that = this
+          // 默认按比例压缩
+          var w = that.width,
+            h = that.height,
+            scale = w / h
+          w = obj.width || w
+          h = obj.height || (w / scale)
+          var quality = 0.7  // 默认图片质量为0.7
+          //生成canvas
+          var canvas = document.createElement('canvas')
+          var ctx = canvas.getContext('2d')
+          // 创建属性节点
+          var anw = document.createAttribute("width")
+          anw.nodeValue = w
+          var anh = document.createAttribute("height")
+          anh.nodeValue = h
+          canvas.setAttributeNode(anw)
+          canvas.setAttributeNode(anh)
+          ctx.drawImage(that, 0, 0, w, h)
+          // 图像质量
+          if (obj.quality && obj.quality <= 1 && obj.quality > 0) {
+            quality = obj.quality
+          }
+          // quality值越小,所绘制出的图像越模糊
+          var base64 = canvas.toDataURL('image/jpeg', quality)
+          // 回调函数返回base64的值
+          return base64
         }
-    }
+      },
+      getIndex(_arr, _obj) {
+        var len = _arr.length;
+        for (let i = 0; i < len; i++) {
+          if (this.isObjEqual(_arr[i],_obj)) {
+            return parseInt(i);
+          }
+        }
+        return -1;
+      },
+      isObjEqual(o1, o2) {
+        var props1 = Object.keys(o1);
+        var props2 = Object.keys(o2);
+        console.log(props1);
+        if (props1.length != props2.length) {
+          return false;
+        }
+        for (var i = 0, max = props1.length; i < max; i++) {
+          var propName = props1[i];
+          if (o1[propName] !== o2[propName]) {
+            return false;
+          }
+        }
+        return true;
+      }
+    },
+    mounted() {
+      this.uploadedList = []
+    },
+    created() {}
+  }
 
 </script>
 <style scoped>
-    .upload-wrap {
+  .upload-file-item {
+    cursor:pointer;
+    color:#909090;
+    margin-top:5px;
+  }
+    .upload-file-item:hover {
+      color:white;
     }
+  .upload-file-name {
+    display:inline-block;
+    margin-left:10px;
+  }
 </style>

Файловите разлики са ограничени, защото са твърде много
+ 18098 - 0
TEAMModelOS/ClientApp/src/utils/azure-storage-blob.js


Файловите разлики са ограничени, защото са твърде много
+ 6 - 0
TEAMModelOS/ClientApp/src/utils/azure-storage-blob.min.js


+ 118 - 0
TEAMModelOS/ClientApp/src/utils/upload-file.js

@@ -0,0 +1,118 @@
+var AccountName = "teammodelostest";
+var SasString = "sv=2019-02-02&ss=bfqt&srt=sco&sp=rwdlacup&se=2019-12-13T10:01:41Z&st=2019-12-13T02:01:41Z&spr=https&sig=0s%2FWA0r7QdtLx4mgCF6nMBwhDZaXLzPAOV5Hig2agDU%3D";
+var ContainerName = "spatest";
+var ContainerURL = undefined;
+let azblobtest = require('./azure-storage-blob');
+console.log('1__________________1');
+//console.log(azblob);
+export default{
+    async init() {
+        this.containerURL = new azblob.ContainerURL(
+            `https://${this.accountName}.blob.core.chinacloudapi.cn/${this.containerName}?${this.sasString}`,
+            azblob.StorageURL.newPipeline(new azblob.AnonymousCredential())
+        );
+    },
+    async deleteFiles(fileList){
+        try {
+            if (fileList.selectedOptions.length > 0) {
+                for (const option of fileList.selectedOptions) {
+                    const blobURL = azblob.BlobURL.fromContainerURL(ContainerURL, option.text);
+                    await blobURL.delete(azblob.Aborter.none);
+                }
+                // this.listFiles();
+            } else {
+                console.log("No files selected.");
+            }
+        } catch (error) {
+            console.log(error.body.message);
+        }
+    },
+    async listFiles(){
+        let fileList = [];
+        try {
+            let marker = undefined;
+            do {
+                const listBlobsResponse = await ContainerURL.listBlobFlatSegment(
+                    azblob.Aborter.none, marker);
+                marker = listBlobsResponse.nextMarker;
+                const items = listBlobsResponse.segment.blobItems;
+                for(const blob of items) {
+                    fileList.push(blob);
+                }
+            } while (marker);
+            if(fileList.size > 0) {
+                this.reportStatus("Done.");
+            } else {
+                this.reportStatus("The container does not contain any files.");
+            }
+        } catch(error) {
+            this.reportStatus(error.body.message);
+        }
+    },
+    async uploadToBlob(file) {
+        const promises = [];
+        const blockBlobURL = azblob.BlockBlobURL.fromContainerURL(
+            this.containerURL,
+            file.name
+        );
+        promises.push(
+            azblob.uploadBrowserDataToBlockBlob(
+                azblob.Aborter.none,
+                file,
+                blockBlobURL
+            )
+        );
+        await Promise.all(promises).then(
+            res =>{
+               console.log(res);     
+
+            },
+            err =>{
+                console.log(err);
+
+            }    
+
+        );
+        this.listFiles();
+        return false;
+    },
+    reportStatus(message) {
+        let status = document.getElementById("status");
+        status.innerHTML += `${message}<br/>`;
+        status.scrollTop = status.scrollHeight;
+    },
+    
+    async createContainer() {
+        try {
+            this.reportStatus(
+                `Creating container "${this.containerName}"...`
+            );
+            await this.containerURL.create(window.azblob.Aborter.none);
+            this.reportStatus(`Done.`);
+        } catch (error) {
+            this.reportStatus(error.body.message);
+        }
+    },
+    async upload() {
+        const blobName = "quickstart" + uuidv1() + ".txt";
+
+        // Get a block blob client
+        const blockBlobClient = containerClient.getBlockBlobClient(
+            blobName
+        );
+
+        console.log("\nUploading to Azure storage as blob:\n\t", blobName);
+
+        // Upload data to the blob
+        const data = "Hello, World!";
+        const uploadBlobResponse = await blockBlobClient.upload(
+            data,
+            data.length
+        );
+        console.log(
+            "Blob was uploaded successfully. requestId: ",
+            uploadBlobResponse.requestId
+        );
+    }
+
+}

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

@@ -378,7 +378,7 @@
             if (res.error == null) {
               this.tableData = res.result.data
               for (let item of this.tableData) {
-                let currentSchoolInfo = this.$JSONPath.query(this.$store.state.schoolBaseInfo.schoolInfo, "$..period[?(@.periodCode=='" + item.classroom.periodCode + "')]")
+                let currentSchoolInfo = this.$JSONPath.query(this.$store.state.schoolBaseInfo.schoolBaseInfo, "$..period[?(@.periodCode=='" + item.classroom.periodCode + "')]")
                 let currentClassroomlInfo = this.$JSONPath.query(this.$store.state.schoolBaseInfo.classroomList, "$..[?(@.classroomCode=='" + item.classroom.classroomCode + "')]")
 
                 if (currentSchoolInfo.length > 0) {

+ 3 - 0
TEAMModelOS/ClientApp/src/view/student-account/add-student/ImportStudent.vue

@@ -269,6 +269,9 @@
             this.tableData.map((item, index) => {
               let val = item.password
               item.password = {}
+              item['classroom'] = {}
+              item.classroom.classroomCode = item.classroomCode
+              item.classroom.classroomName = item.classroomName
               item.password['value'] = val
               return item
             })

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

@@ -276,72 +276,12 @@
         right: 50px;
     }
 }
-/*.card-item {
-    cursor: pointer;
-    width: 260px;
-    height: 380px;
-    border: 1px solid @borderColor;
-    background: #505050;
-    margin: 10px 12px;
-    position: relative;
-    display: inline-block;
-    border-radius: 5px;
-    color: white;
-    text-align: center;
-
-    &:hover {
-        box-shadow: 0 26px 40px -24px rgb(0,0,0);
-        transform: translateY(-6px);
-        transition: all .2s ease 0s;
-        background: #606060;
-    }
 
-    .file-icon {
-        width: 100%;
-        padding: 20px 0px;
-        display:inline-block;
-        img{
-            display:inline-block;
-            margin-top:4px;
-        }
-    }
-
-    .file-action {
-        position: absolute;
-        bottom: 20px;
-        left: 50px;
-    }
-
-    .file-info {
-        p {
-            font-size: 20px;
-            color: white;
-            height: 65px;
-            display: -webkit-box;
-            -webkit-box-orient: vertical;
-            -webkit-line-clamp: 2;
-            overflow: hidden;
-            padding: 0px 15px;
-            text-align:left;
-            word-break:break-all;
-        }
-
-        .file-detail-info {
-            margin-top: 10px;
-            text-align: left;
-            padding: 0px 15px;
-            color: #DDDDDD;
-
-            span {
-                display: block;
-                margin-bottom: 10px;
-            }
-        }
-    }
-}*/
 .card-item {
     width: 300px;
     height: fit-content;
+    max-height:200px;
+    overflow:hidden;
     position: relative;
     margin: auto;
     margin-top: 15px;

Файловите разлики са ограничени, защото са твърде много
+ 556 - 1179
TEAMModelOS/ClientApp/src/view/teachcontent/index.vue


+ 8 - 5
TEAMModelOS/Controllers/Core/StudentController.cs

@@ -44,7 +44,7 @@ namespace TEAMModelOS.Controllers.Syllabus
                 periodCode = request.@params.classroom.periodCode,
                 schoolCode = request.@params.classroom.schoolCode,
             };
-            request.@params.id = classroom.schoolCode + request.@params.studentId;
+            request.@params.id = request.@params.studentId.Replace("#","-");
             request.@params.classroom = classroom;
             Student data = await azureCosmosDBRepository.Save<Student>(request.@params);
             return builder.Data(data).build();
@@ -88,10 +88,13 @@ namespace TEAMModelOS.Controllers.Syllabus
                         Student student = new Student
                         {
                             schoolCode = classrooms[0].schoolCode,
-                            id = x.schoolCode + x.studentId,
-                            TEAMModelId = x.schoolCode + "#" + x.studentId,
-                            virtualId = x.schoolCode + "#" + x.studentId,
-                            createDate = createDate
+                            id = x.studentId.Replace("#","-"),
+                         //   TEAMModelId = x.studentId,
+                           // virtualId = x.studentId,
+                            createDate = createDate,
+                            name = x.name,
+                            seatNo = x.seatNo,
+                            studentId = x.studentId
                         };
                         //设置密码 isSet 是否加密 如果加密则不会再次加密
                         if (!x.password.isSet) {