瀏覽代碼

暂存,待联调

hbchen 1 年之前
父節點
當前提交
ea8c76aebc

二進制
src/assets/img/document_m/audio-start.png


二進制
src/assets/img/icons/arrow_black_up.png


二進制
src/assets/img/icons/arrow_left_black.png


二進制
src/assets/img/icons/close.png


二進制
src/assets/img/icons/copy-active.png


二進制
src/assets/img/icons/copy.png


二進制
src/assets/img/icons/eyes-hide-active.png


二進制
src/assets/img/icons/eyes-hide.png


二進制
src/assets/img/icons/eyes-show-active.png


二進制
src/assets/img/icons/eyes-show.png


二進制
src/assets/img/tag-gray.png


+ 31 - 0
src/directives/tooltip-hidable.js

@@ -0,0 +1,31 @@
+// 长度溢出显示ToolTip 请绑定的标签元素包裹住 element-ui的el-tooltip。
+/**
+ * binding.value 为长度溢出的元素的css选择器,没有请设置
+ */
+import { Message } from "element-ui"
+
+export default {
+  bind(el,binding,vnode) {
+    try {
+      const resizeObserver = new ResizeObserver(entries => {
+        // console.log('监听到了尺寸变化了...',entries)
+        // console.log(el.scrollWidth,el.clientWidth);
+          if(el.scrollWidth > el.clientWidth){
+            // 超出
+            vnode.componentInstance.disabled=false
+          }else{
+            vnode.componentInstance.disabled=true
+          }
+      })
+      setTimeout(()=>{
+        resizeObserver.observe(el)
+      },0)
+    } catch (error) {
+      console.error(error);
+      Message.error(error.message)
+    }
+  },
+  updated(el,binding,vnode) {
+    console.log('updated');
+  },
+}

+ 1 - 1
src/utils/common.js

@@ -294,7 +294,7 @@ const handleUploadToS3=(file,fileName,options={})=>{
                     Body: file,
                     ACL: "public-read",
                     Key: fileName
-                }, function (err, data) {
+                },options, function (err, data) {
                     if (err) {
                         console.log("Error! err =====> ", err);
                         throw new Error("上传到s3失败!")

File diff suppressed because it is too large
+ 795 - 192
src/views/semantics_manage/asr/ASR.vue


+ 81 - 21
src/views/semantics_manage/asr/components/audioCustom.vue

@@ -1,11 +1,17 @@
 <template>
   <div class="audio-container">
-    <audio :src="audioUrl">Your browser does not support the audio element.</audio>
-    <img src="~@/assets/img/document_m/audio-backward.png" />
-    <img src="~@/assets/img/document_m/audio-stop.png" style="height: 30px;width: 30px;"/>
-    <img src="~@/assets/img/document_m/audio-forward.png"/>
-    <div class="progress-line"><div class="progress-line-played" style="width: 50%;"></div></div>
-    <div class="played-time">00:00</div>
+    <audio :src="audioUrl" ref="audioUrlRef" @timeupdate="updateProgress" @ended="audioEnded"
+    @loadedmetadata="setDuration">
+      Your browser does not support the audio element.
+    </audio>
+    <img src="~@/assets/img/document_m/audio-backward.png" @click="skipTime(-15)" />
+    <img :src="isPlaying?require('@/assets/img/document_m/audio-start.png'):require('@/assets/img/document_m/audio-stop.png')" style="height: 30px;width: 30px;"
+    @click="togglePlay"/>
+
+    <img src="~@/assets/img/document_m/audio-forward.png"  @click="skipTime(15)"/>
+    <el-slider v-model="currentTime" :show-tooltip="false" class="progress-line"
+    @input="handleDragTime" :max="duration"/>
+    <div class="played-time">{{ formatTime(currentTime) }}</div>
     <el-dropdown @command="setSpeed" class="dropdown-speed">
       <span>倍速 {{ speed }}x</span>
       <el-dropdown-menu slot="dropdown">
@@ -29,14 +35,64 @@
     },
     data() {
       return {
-        speed:1
+        isPlaying:false,
+        speed:1,
+        currentTime: 0,
+        duration: 0,
+        playbackRate: 1, // 倍速率,默认为1
+        showHours:true
       }
     },
     methods: {
+      togglePlay(){
+        const audio = this.$refs.audioUrlRef;
+        if(this.isPlaying){
+          audio.pause()
+        }else{
+          audio.play()
+        }
+        this.isPlaying=!this.isPlaying
+      },
+      updateProgress(event) {
+        const { currentTime } = event.target;
+        this.currentTime = currentTime;
+      },
+      skipTime(seconds) {
+        const audio = this.$refs.audioUrlRef;
+
+        audio.currentTime += seconds;
+        if(audio.currentTime < 0) audio.currentTime = 0;
+        if(audio.currentTime > audio.duration) audio.currentTime = audio.duration;
+      },
+      setDuration(event){
+        this.duration = event.target.duration;
+        this.showHours = Math.floor(this.duration / 3600) > 0
+      },
+      audioEnded() {
+        this.isPlaying = false; // 音频结束时更新播放状态
+      },
       setSpeed(s){
+        const audio = this.$refs.audioUrlRef;
         this.speed=s
-        console.log(s);
-      }
+
+        audio.playbackRate = this.speed;
+      },
+      handleDragTime(e){
+        const audio = this.$refs.audioUrlRef;
+        audio.currentTime = e
+      },
+      formatTime(timeInSeconds) {
+        
+        const hours = Math.floor(timeInSeconds / 3600);
+        const minutes = Math.floor((timeInSeconds % 3600) / 60);
+        const seconds = Math.floor(timeInSeconds % 60);
+        const result =
+        this.showHours
+        ? `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
+        : `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
+
+        return result;
+      },
     },
   }
 </script>
@@ -58,20 +114,8 @@
     cursor: pointer;
   }
   .progress-line{
-    position: relative;
-    height: 3px;
     flex-grow: 1;
-    background-color: white;
     margin-right: 20px;
-    cursor: pointer;
-    .progress-line-played{
-      height: 3px;
-      position: absolute;
-      top: 0;
-      left: 0;
-      background-color: #0052D9;
-      pointer-events: none;
-    }
   }
   .played-time{
     margin-right: 40px;
@@ -96,4 +140,20 @@
     color: #0052D9;
     background-color: #e6eefb;
   }
+  .el-slider__runway{
+    background-color: white;
+    height: 3px;
+    .el-slider__bar{
+      height: 3px;
+    }
+    .el-slider__button-wrapper{
+      height: 18px;
+      width: 18px;
+      transform: translate(-50%,calc(50% - 2px));
+      .el-slider__button{
+        height: 8px;
+        width: 8px;
+      }
+    }
+  }
 </style>

+ 100 - 0
src/views/semantics_manage/asr/components/catalogueDia.vue

@@ -0,0 +1,100 @@
+<template>
+	<el-dialog
+		:visible.sync="diaShow"
+		:close-on-click-modal="false"
+		:modal-append-to-body='false'
+    :title="diaTitle"
+		@close="closeHandle"
+		center
+		width="480px">
+			<div class="dialog-main">
+				<el-form
+				ref="diaForm"
+				label-position="top"
+				hide-required-asterisk
+				:model="formData">
+          <el-form-item :label="(index+1)==formData.level?'目录名称':getFormLabel(index,formData.level)" 
+          :rules="{required:true,message:'目录名称必填',trigger:'blur'}" :prop="formProps[index]" 
+          v-for="(item,index) in new Array(formData.level)" :key="index">
+            <el-input v-model="formData.one" style="width: 100%" placeholder="必填项" v-if="index==0" :disabled="formData.level!=1"></el-input>
+            <el-input v-model="formData.two" style="width: 100%" placeholder="必填项" v-else-if="index==1" :disabled="formData.level!=2"></el-input>
+            <el-input v-model="formData.three" style="width: 100%" placeholder="必填项" v-else></el-input>
+          </el-form-item>
+				</el-form>
+        <div class="dia-bot">
+          <el-button type="primary" plain style="margin-right:20px;min-width:120px ;" @click="cancelHandle">取消</el-button>
+          <el-button type="primary" @click="saveHandle" style="min-width:120px;">保存</el-button>
+        </div>
+			</div>
+		</el-dialog>
+</template>
+
+<script>
+  export default {
+    name:"catalogueDia",
+    props:{
+      formData:{
+        type:Object,
+        default:()=>{
+          return {}
+        }
+      },
+      diaShow:{
+        type:Boolean,
+        default:false
+      }
+    },
+    watch:{
+      diaShow(value){
+        if(value){
+          console.log(this.formData,'formData');
+          this.diaTitle = this.formData.id?"编辑":"添加"
+          this.$refs.diaForm && this.$nextTick(()=>{
+            this.$refs.diaForm.clearValidate()
+          })
+        }
+      }
+    },
+    data() {
+      return {
+        diaTitle:'',
+        formProps:['one','two','three']
+      }
+    },
+    methods: {
+      cancelHandle(){
+        this.$emit("update:diaShow",false)
+      },
+      saveHandle(){
+        this.$refs.diaForm.validate(valid=>{
+          if(valid){
+            //TODO: 保存目录接口
+            this.$message.success(this.diaTitle+"成功")
+            this.$emit("catalogueSuccess")
+            this.$emit("update:diaShow",false)
+          }
+        })
+      },
+      getFormLabel(index,level){
+        if(level==2){
+          return "上级目录"
+        }
+        let levelLabel=['一级目录','二级目录']
+        return levelLabel[index]
+      },
+      closeHandle(){
+        this.$emit("update:diaShow",false)
+      }
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+.dialog-main{
+  padding: 5px 35px 35px;
+  .dia-bot{
+    text-align: center;
+    margin-top: 60px;
+  }
+}
+</style>

+ 108 - 0
src/views/semantics_manage/asr/components/editTag.vue

@@ -0,0 +1,108 @@
+<template>
+	<el-dialog
+		:visible.sync="diaShow"
+		:close-on-click-modal="false"
+		:modal-append-to-body='false'
+    :title="diaTitle"
+		@close="closeHandle"
+		center
+		width="480px">
+			<div class="dialog-main">
+				<el-form
+				ref="diaForm"
+				label-position="top"
+				hide-required-asterisk
+				:model="formData">
+          <el-form-item label="标签名称" :rules="{required:true,message:'标签名称必填',trigger:'blur'}" prop="name">
+            <el-input v-model="formData.name" style="width: 100%" placeholder="请输入标签名称"></el-input>
+          </el-form-item>
+          <el-form-item label="所属目录" :rules="{required:true,message:'所属目录必填',trigger:'change'}" prop="catalogue"
+          v-if="!formData.id">
+            <el-cascader v-model="formData.catalogue" placeholder="请选择标签目录" clearable id="edit-tag-cascader"
+              :options="tagCatalogue" :props="{value:'fsdfsfssdefffe',label:'ChartClassifyName',children:'Children',checkStrictly:true}"
+              style="width: 100%;"></el-cascader>
+          </el-form-item>
+				</el-form>
+        <div class="dia-bot">
+          <el-button type="primary" plain style="margin-right:20px;min-width:120px ;" @click="cancelHandle">取消</el-button>
+          <el-button type="primary" @click="saveHandle" style="min-width:120px;">保存</el-button>
+        </div>
+			</div>
+		</el-dialog>
+</template>
+
+<script>
+  export default {
+    name:"editTag",
+    props:{
+      formData:{
+        type:Object,
+        default:()=>{
+          return {}
+        }
+      },
+      diaShow:{
+        type:Boolean,
+        default:false
+      },
+      tagCatalogue:{
+        type:Array,
+        required:true
+      }
+    },
+    watch:{
+      diaShow(value){
+        if(value){
+          console.log(this.formData,'formData');
+          this.diaTitle = this.formData.id?"编辑标签":"添加标签"
+          this.$refs.diaForm && this.$nextTick(()=>{
+            this.$refs.diaForm.clearValidate()
+          })
+        }
+      }
+    },
+    data() {
+      return {
+        diaTitle:'',
+      }
+    },
+    methods: {
+      cancelHandle(){
+        this.$emit("update:diaShow",false)
+      },
+      saveHandle(){
+        this.$refs.diaForm.validate(valid=>{
+          if(valid){
+            //TODO: 保存目录接口
+            this.$message.success(this.diaTitle+"成功")
+            this.$emit("tagSuccess")
+            this.$emit("update:diaShow",false)
+          }
+        })
+      },
+      closeHandle(){
+        this.$emit("update:diaShow",false)
+      }
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+.dialog-main{
+  padding: 5px 35px 35px;
+  .dia-bot{
+    text-align: center;
+    margin-top: 60px;
+  }
+}
+</style>
+<style lang="scss">
+  .el-cascader-node{
+    max-width: 200px;
+  }
+#edit-tag-cascader{
+  .el-input{
+    width: 100%;
+  }
+}
+</style>

+ 95 - 0
src/views/semantics_manage/asr/components/exportDia.vue

@@ -0,0 +1,95 @@
+<template>
+	<el-dialog
+		:visible.sync="diaShow"
+		:close-on-click-modal="false"
+		:modal-append-to-body='false'
+    :title="diaTitle"
+		@close="closeHandle"
+		center
+		width="480px">
+			<div class="dialog-main">
+				<el-form
+				ref="diaForm"
+				label-position="top"
+				hide-required-asterisk
+				:model="formData">
+          <el-form-item label="文件格式" :rules="{required:true,message:'文件格式必填',trigger:'change'}" prop="type">
+            <el-select v-model="formData.type" placeholder="请选择文件格式" style="width: 100%">
+              <el-option :label="item.label" :value="item.value" v-for="item in exportType" :key="item.value"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="显示信息" prop="shows">
+            <el-select v-model="formData.shows" placeholder="请选择显示信息" style="width: 100%">
+              <el-option :label="item.label" :value="item.value" v-for="item in showsList" :key="item.value"></el-option>
+            </el-select>
+          </el-form-item>
+				</el-form>
+        <div class="dia-bot">
+          <el-button type="primary" plain style="margin-right:20px;min-width:120px ;" @click="cancelHandle">取消</el-button>
+          <el-button type="primary" @click="saveHandle" style="min-width:120px;">保存</el-button>
+        </div>
+			</div>
+		</el-dialog>
+</template>
+
+<script>
+  export default {
+    name:"exportDia",
+    props:{
+      formData:{
+        type:Object,
+        default:()=>{
+          return {}
+        }
+      },
+      diaShow:{
+        type:Boolean,
+        default:false
+      }
+    },
+    watch:{
+      diaShow(value){
+        if(value){
+          this.$refs.diaForm && this.$nextTick(()=>{
+            this.$refs.diaForm.clearValidate()
+          })
+        }
+      }
+    },
+    data() {
+      return {
+        diaTitle:'导出内容',
+        exportType:[{value:"doc",label:".doc"},{value:"pdf",label:".pdf"},{value:"txt",label:".txt"}],
+        showsList:[{value:"timestamp",label:"时间戳"}]
+      }
+    },
+    methods: {
+      cancelHandle(){
+        this.$emit("update:diaShow",false)
+      },
+      saveHandle(){
+        this.$refs.diaForm.validate(valid=>{
+          if(valid){
+            //TODO: 导出接口
+            this.$message.success("导出成功")
+            // this.$emit("exportSuccess")
+            this.$emit("update:diaShow",false)
+          }
+        })
+      },
+      closeHandle(){
+        this.$emit("update:diaShow",false)
+      }
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+.dialog-main{
+  padding: 5px 35px 35px;
+  .dia-bot{
+    text-align: center;
+    margin-top: 60px;
+  }
+}
+</style>

+ 60 - 59
src/views/semantics_manage/asr/components/fileRename.vue

@@ -1,85 +1,86 @@
 <template>
 	<el-dialog
-		:visible.sync="isOpenDialog"
+		:visible.sync="diaShow"
 		:close-on-click-modal="false"
 		:modal-append-to-body='false'
-		@close="cancelHandle"
+    :title="diaTitle"
+		@close="closeHandle"
 		center
-		width="500px">
-			<div slot="title" style="display:flex;alignItems:center;">
-				<img :src="title=='添加'?$icons.add:title=='编辑'?$icons.edit:''" style="color:#fff;width:16px;height:16px;marginRight:5px;">
-				<span style="fontSize:16px;">{{title}}</span>
-			</div>
+		width="480px">
 			<div class="dialog-main">
 				<el-form
 				ref="diaForm"
-				label-position="left"
+				label-position="top"
 				hide-required-asterisk
-				label-width="80px"
-				:model="formData"
-				:rules="formRules">
-					<!-- 添加/编辑1级目录 -->
-					<template 
-					v-if="(title=='添加'&&formData.level === 0)
-					|| (title=='编辑'&&formData.level === 1)">
-						<el-form-item label="分类名称" prop="level_1">
-							<el-input
-							v-model="formData.level_1"
-							style="width: 80%"
-							placeholder="必填项"></el-input>
-						</el-form-item>
-					</template>
-					<!-- 添加/编辑2级目录 -->
-					<template 
-					v-else-if="(title=='添加'&&formData.level === 1)
-					|| (title=='编辑'&&formData.level === 2)">
-						<el-form-item label="一级目录" prop="level_1">
-							<span>{{formData.level_1}}</span>
-						</el-form-item>
-						<el-form-item label="分类名称" prop="level_2">
-							<el-input
-							v-model="formData.level_2"
-							style="width: 80%"
-							placeholder="必填项"></el-input>
-						</el-form-item>
-					</template>
-					<!-- 添加/编辑三级目录 -->
-					<template v-else-if="(title=='添加'&&formData.level === 2)
-					|| (title=='编辑'&&formData.level === 3)">
-						<el-form-item label="一级目录" prop="level_1">
-							<span>{{formData.level_1}}</span>
-						</el-form-item>
-						<el-form-item label="二级目录" prop="level_2">
-							<span>{{formData.level_2}}</span>
-						</el-form-item>
-						<el-form-item label="分类名称" prop="level_3">
-							<el-input
-							v-model="formData.level_3"
-							style="width: 80%"
-							placeholder="必填项"></el-input>
-						</el-form-item>
-					</template>
+				:model="formData">
+          <el-form-item label="文件名称" :rules="{required:true,message:'文件名称必填',trigger:'blur'}" prop="name">
+            <el-input v-model="formData.name" style="width: 100%" placeholder="请输入文件名称"></el-input>
+          </el-form-item>
 				</el-form>
-			</div>
-			<div class="dia-bot">
-				<el-button type="primary" style="margin-right:20px" @click="saveHandle">保存</el-button>
-				<el-button type="primary" plain @click="cancelHandle">取消</el-button>
+        <div class="dia-bot">
+          <el-button type="primary" plain style="margin-right:20px;min-width:120px ;" @click="cancelHandle">取消</el-button>
+          <el-button type="primary" @click="saveHandle" style="min-width:120px;">保存</el-button>
+        </div>
 			</div>
 		</el-dialog>
-
 </template>
 
 <script>
   export default {
     name:"fileRename",
+    props:{
+      formData:{
+        type:Object,
+        default:()=>{
+          return {}
+        }
+      },
+      diaShow:{
+        type:Boolean,
+        default:false
+      }
+    },
+    watch:{
+      diaShow(value){
+        if(value){
+          this.$refs.diaForm && this.$nextTick(()=>{
+            this.$refs.diaForm.clearValidate()
+          })
+        }
+      }
+    },
     data() {
       return {
-        
+        diaTitle:'重命名',
+      }
+    },
+    methods: {
+      cancelHandle(){
+        this.$emit("update:diaShow",false)
+      },
+      saveHandle(){
+        this.$refs.diaForm.validate(valid=>{
+          if(valid){
+            //TODO: 重命名保存接口
+            this.$message.success(this.diaTitle+"成功")
+            this.$emit("renameSuccess")
+            this.$emit("update:diaShow",false)
+          }
+        })
+      },
+      closeHandle(){
+        this.$emit("update:diaShow",false)
       }
     },
   }
 </script>
 
 <style lang="scss" scoped>
-
+.dialog-main{
+  padding: 5px 35px 35px;
+  .dia-bot{
+    text-align: center;
+    margin-top: 60px;
+  }
+}
 </style>

+ 246 - 0
src/views/semantics_manage/asr/components/makeTags.vue

@@ -0,0 +1,246 @@
+<template>
+	<el-dialog
+		:visible.sync="diaShow"
+		:close-on-click-modal="false"
+		:modal-append-to-body='false'
+    :title="diaTitle"
+		@close="closeHandle"
+		center
+		width="800px"
+    top="5vh">
+			<div class="dialog-main">
+        <div class="make-tags-header">
+          <el-checkbox :indeterminate="isIndeterminate" v-model="isCheckAll" @change="checkAllTags">全选</el-checkbox>
+          <el-input v-model="tagSeachWord" placeholder="请输入标签名称" prefix-icon="el-icon-search" clearable
+              style="width: 360px;" @input="searchTags"></el-input>
+        </div>
+        <div class="make-tags-list">
+          <el-checkbox-group v-model="formData.tagsArr" class="make-tags-group" ref="tagsGroupRef" 
+          v-if="tagsListAfterFilter && tagsListAfterFilter.length>0" @change="tagsCheckedChange">
+            <el-checkbox :label="item.tagId" v-for="item in tagsListAfterFilter" :key="item.tagId" style="margin-right: 0;"> {{ item.tagName }}</el-checkbox>
+          </el-checkbox-group>
+          <tableNoData text="暂无数据" v-else />
+        </div>
+        <div class="make-tags-add">
+          <div class="make-tags-add-title">添加标签</div>
+          <el-form
+          ref="tagsForm" class="tags-form"
+          label-position="top" inline
+          hide-required-asterisk
+          :model="addTagsForm">
+            <el-form-item :rules="{required:true,message:'标签名称必填',trigger:'blur'}" prop="tagName">
+              <el-input v-model="addTagsForm.tagName" placeholder="请输入标签名称" style="width: 260px"></el-input>
+            </el-form-item>
+            <el-form-item prop="tagCatalogue"  :rules="{required:true,message:'标签目录必填',trigger:'change'}">
+              <el-cascader v-model="addTagsForm.tagCatalogue" placeholder="请选择标签目录" id="make-tags-cascader" style="width: 260px"
+              :options="tagCatalogueList" :props="{value:'UniqueCode',label:'ChartClassifyName',children:'Children',checkStrictly:true}"></el-cascader>
+            </el-form-item>
+            <el-button type="primary" style="width: 100px;" @click="addTag">添加</el-button>
+          </el-form>
+        </div>
+        <div class="dia-bot">
+          <el-button type="primary" plain style="margin-right:20px;min-width:120px ;" @click="cancelHandle">取消</el-button>
+          <el-button type="primary" @click="saveHandle" style="min-width:120px;">保存</el-button>
+        </div>
+			</div>
+		</el-dialog>
+</template>
+
+<script>
+  export default {
+    name:"makeTags",
+    props:{
+      formData:{
+        type:Object,
+        default:()=>{
+          return {}
+        }
+      },
+      diaShow:{
+        type:Boolean,
+        default:false
+      },
+      tagsList:{
+        type:Array,
+        required:true
+      },
+      tagCatalogueList:{
+        type:Array,
+        required:true
+      }
+    },
+    watch:{
+      diaShow(value){
+        if(value){
+          this.updateTagsList()
+          this.tagsCheckedChange()
+        }
+      },
+    },
+    data() {
+      return {
+        diaTitle:'打标签',
+        tagSeachWord:"",
+        isIndeterminate:false,
+        isCheckAll:false,
+        tagsListAfterFilter:[],
+        addTagsForm:{
+          tagName:'',
+          tagCatalogue:''
+        },
+        hasAddTag:false
+      }
+    },
+    methods: {
+      checkAllTags(){
+        this.isIndeterminate=false
+        if(this.isCheckAll){
+          this.formData.tagsArr=this.tagsList.map(item => item.tagId)
+        }else{
+          this.formData.tagsArr=[]
+        }
+      },
+      cancelHandle(){
+        this.$emit("update:diaShow",false)
+      },
+      closeHandle(){
+        if(this.hasAddTag){
+          this.$emit("updateTagsTree")
+        }
+        this.addTagsForm={
+          tagName:'',
+          tagCatalogue:''
+        }
+        this.hasAddTag=false
+        this.tagSeachWord=""
+        this.$refs.tagsForm && this.$nextTick(()=>{
+          this.$refs.tagsForm.clearValidate()
+        })
+        this.$emit("update:diaShow",false)
+      },
+      searchTags(){
+        console.log(this.tagSeachWord);
+        this.updateTagsList('top')
+      },
+      tagsCheckedChange(value){
+        console.log(value,this.formData.tagsArr,'this.formData.tagsArr');
+        if(!( (this.formData.tagsArr && this.formData.tagsArr.length>0) && (this.tagsList && this.tagsList.length>0) )){
+          this.isIndeterminate=false
+          this.isCheckAll=false
+        }else if(this.formData.tagsArr.length<this.tagsList.length){
+          this.isIndeterminate=true
+          this.isCheckAll=false
+        }else{
+          this.isIndeterminate=false
+          this.isCheckAll=true
+        }
+      },
+      updateTagsList(scrollType){
+        this.tagsListAfterFilter=this.tagsList.filter(tag => tag.tagName.indexOf(this.tagSeachWord)!=-1)
+        switch (scrollType) {
+          case "top":
+            this.$nextTick(()=>{
+              this.$refs.tagsGroupRef && this.$refs.tagsGroupRef.$el.scrollTo(0,0)
+            })
+            break;
+          case "bottom":
+            this.$nextTick(()=>{
+              this.$refs.tagsGroupRef && this.$refs.tagsGroupRef.$el.scrollTo(0,this.$refs.tagsGroupRef.$el.scrollHeight)
+            })
+            break;
+        }
+      },
+      addTag(){
+        console.log(this.addTagsForm);
+        this.$refs.tagsForm.validate(valid=>{
+          if(valid){
+            //TODO: 新增标签接口
+            this.$message.success("新增标签成功")
+            this.addTagsForm={
+              tagName:'',
+              tagCatalogue:''
+            }
+            this.formData.tagsArr.push('16')
+            this.tagsCheckedChange()
+            this.hasAddTag=true
+            this.$emit("addTagSuccess")
+          }
+        })
+      },
+      saveHandle(){
+        //TODO: 打标签接口
+        this.$message.success("打标签成功")
+        this.$emit("update:diaShow",false)
+        // console.log(this);
+        let tagsData=this.tagsList.filter(tag => this.formData.tagsArr.includes(tag.tagId))
+        this.$emit("makeTagsSuccess",tagsData)
+      },
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+.dialog-main{
+  padding: 5px 35px 35px;
+  .make-tags-header{
+    display: flex;
+    align-items: flex-end;
+    justify-content: space-between;
+  }
+  .make-tags-list{
+    margin-top: 20px;
+    padding: 20px;
+    box-sizing: border-box;
+    background-color: #ECF2FE;
+    border: solid 1px #C8CDD9;
+    border-radius: 4px;
+    .make-tags-group{
+      display: flex;
+      flex-direction: column;
+      gap: 20px;
+      max-height: 360px;
+      overflow: auto;
+    }
+  }
+  .make-tags-add{
+    margin-top: 30px;
+    .make-tags-add-title{
+      font-size: 14px;
+      line-height: 22px;
+      font-family: 400;
+      color: #333333;
+    }
+    .tags-form{
+      margin-top: 10px;
+      display: flex;
+      align-items: flex-start;
+      justify-content: space-between;
+    }
+  }
+  .dia-bot{
+    text-align: center;
+    margin-top: 60px;
+  }
+}
+</style>
+<style lang="scss">
+  .el-cascader-node{
+    max-width: 200px;
+  }
+#make-tags-cascader{
+  .el-input{
+    width: 100%;
+  }
+}
+
+.make-tags-group{
+  .el-checkbox{
+    margin-right: 0;
+    display: flex;
+    .el-checkbox__label{
+      word-break: break-all;
+      white-space: normal;
+    }
+  }
+}
+</style>

+ 426 - 0
src/views/semantics_manage/asr/components/mediaUpload.vue

@@ -0,0 +1,426 @@
+<template>
+  <div>
+	<el-dialog
+		:visible.sync="diaShow"
+		:close-on-click-modal="false"
+		:modal-append-to-body='false'
+    :title="diaTitle"
+		@close="closeHandle"
+		center top="10vh"
+		width="800px">
+			<div class="dialog-main">
+				<el-form
+				ref="diaForm"
+				label-position="left"
+				hide-required-asterisk
+				:model="formData">
+          <el-form-item label="所属目录" :rules="{required:true,message:'所属目录必填',trigger:'change'}" 
+          prop="catalogue" label-width="76px">
+            <el-cascader v-model="formData.catalogue" placeholder="请选择所属目录" clearable id="media-upload-cascader"
+              :options="articleCatalogue" :props="{value:'UniqueCode',label:'ChartClassifyName',children:'Children',checkStrictly:true}"
+              style="width: 604px;"></el-cascader>
+          </el-form-item>
+				</el-form>
+        <div class="file-upload-zone">
+          <div class="file-upload-title">
+            <span>文件数量:{{ fileList.length }} / {{ this.fileLimit }}</span>
+            <span v-if="fileList.length>0" class="file-readdition" 
+              :class="{'disable-readdition':!( (this.fileList.length+this.uploadingFileNames.length) <fileLimit)}" @click="uploadClick">继续添加</span>
+          </div>
+          <div class="file-upload-main" id="drop-upload-zone" @dragover="uploadDragover" @drop="uploadDrop">
+            <el-table :data="fileList" id="file-list-table">
+              <el-table-column label="文件名" prop="name" show-overflow-tooltip >
+                <template slot-scope="{row}">
+                  <span class="table-span">{{ row.name }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="大小" prop="size" width="120">
+                <template slot-scope="{row}" >
+                  <span class="table-span">{{ row.size }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="音/视频" prop="type" width="100">
+                <template slot-scope="{row}">
+                  <span class="table-span">{{ row.type }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column label="操作" prop="operation" width="60">
+                <template slot-scope="{row,$index}">
+                  <span class="table-button" @click="deleteFile($index)">删除</span>
+                </template>
+              </el-table-column>
+                  <div slot="empty" class="no-file-show" @click="uploadClick">
+                    <div class="upload-text"><span style="color:#0052D9 ;">点击/拖拽</span>本地音视频文件</div>
+                    <div class="upload-message-box">
+                      <div class="upload-message-row">支持音频格式:mp3、wav、m4a、amr、wma、aac、ogg-opus、flac</div>
+                      <div class="upload-message-row">支持视频格式:mp4、flv、3gp</div>
+                      <div class="upload-message-row">单个文件最长5小时、最大1GB,单次支持上传50个</div>
+                    </div>
+                  </div>
+            </el-table>
+          </div>
+        </div>
+        <div class="dia-bot">
+          <el-button type="primary" plain style="margin-right:20px;min-width:120px ;" @click="cancelHandle">取消</el-button>
+          <el-button type="primary" @click="saveHandle" style="min-width:120px;" :disabled="fileList.length==0">开始转写</el-button>
+        </div>
+        <!-- :http-request="handleUpload"
+          :before-upload="handleBeforeUpload" -->
+        <el-upload 
+          ref="uploadRef" id="upload-media" style="display: none;"
+          accept=".mp3,.wav,.m4a,.amr,.wma,.aac,.opus,.ogg,.flac,.mp4,.flv,.3gp"
+          action="#" multiple :limit="fileLimit"
+          :on-change="uploadMedia"
+          :show-file-list="false"
+          :auto-upload="false"
+          :disabled="!((this.fileList.length+this.uploadingFileNames.length)<fileLimit)">
+        </el-upload>
+			</div>
+		</el-dialog>
+</div>
+</template>
+
+<script>
+import {uploadFileDirect} from "@/utils/common.js"
+  export default {
+    name:"editTag",
+    props:{
+      diaShow:{
+        type:Boolean,
+        default:false
+      },
+      articleCatalogue:{
+        type:Array,
+        required:true
+      }
+    },
+    watch:{
+      uploadingFileNames(value){
+        if(!(value && value.length>0)){
+          if(this.uploadHint){
+            this.uploadHint.close()
+            this.uploadHint=null
+          }
+          if(this.closeDia) return 
+          this.$message.success("上传成功,请检查转写列表")
+        }
+      },
+      diaShow(value){
+        if(value){
+          this.current++
+        }
+      }
+    },
+    data() {
+      return {
+        last:0,
+        current:0,
+        diaTitle:'上传本地音视频文件',
+        formData:{
+          catalogue:''
+        },
+        fileLimit:50,
+        fileExp:new RegExp(/\.(mp3|wav|m4a|amr|wma|aac|opus|ogg|flac|mp4|flv|3gp)$/,'i'),
+        fileList:[
+        {name:"fdsfsa.mp4",size:"1021.26M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        ],
+        // {name:"fdsfsa.mp4",size:"1021.26M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.26M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.26M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},
+        // {name:"fdsfsa.mp4",size:"1021.2M",type:"音频"},{name:"fdsfsa.mp4",size:"1021.2M",type:"音频"}
+        uploadingFileNames:[],
+        uploadHint:null,
+        closeDia:false
+      }
+    },
+    methods: {
+      uploadClick(){
+        if(!( (this.fileList.length+this.uploadingFileNames.length) < this.fileLimit)) return 
+        $('#upload-media input').trigger('click')
+      },
+      uploadDragover(event){
+        event.preventDefault(); //阻止默认行为,允许放置
+      },
+      uploadDrop(event){
+        event.preventDefault(); //阻止浏览器默认行为
+        // 获取文件的数据
+        const DataTransferItemList = event.dataTransfer.files
+        DataTransferItemList.forEach(file =>{
+          file.raw=file
+          setTimeout(()=>{
+            this.uploadMedia(file)
+          })
+        })
+      },
+      async uploadMedia(file){
+        console.log(file);
+        if(this.uploadingFileNames.some(item=> item.split('.')[0] == file.name.split('.')[0])){
+          return this.$message.error(file.name+'同名文件正在上传,请稍后重试')
+        }
+        if(!(this.fileExp.test(file.name))){
+          return this.$message.error(file.name+'格式不受支持')
+        }
+        if(!(file.size/1024/1024 < 1024.1)){
+          return this.$message.error(file.name+'大小已超限')
+        }
+
+        let res = await this.checkDuration(file)
+        if(!res.flag){
+          return this.$message.error(res.msg);
+        }
+
+        if(!( (this.fileList.length+this.uploadingFileNames.length) < this.fileLimit)){
+          return this.$message.error(`上传文件已超过${this.fileLimit}个,${file.name}上传失败`)
+        } 
+        // TODO: 调用接口判断是否与数据库的文件重复
+
+        if(!this.uploadHint){
+          this.uploadHint = this.$message({
+            type:"info",
+            message:'上传中,请勿关闭弹窗',
+            duration:0,
+            iconClass:'el-icon-loading'
+          })
+        }
+        // 上传
+        let fileFront=file.name.split('.')[0]
+        this.uploadingFileNames.push(fileFront)
+
+        let temName = `asr/media/${new Date().getTime()}`
+        let clientType = this.$setting.dynamicOutLinks.ObjectStorageClient ||
+                  this.$store.state.dynamicOutLinks.ObjectStorageClient ||
+                  JSON.parse(localStorage.getItem('dynamicOutLinks')).ObjectStorageClient
+        let options={}
+        if((file.size/1024/1024 > 200)){
+          // 大于200MB,分片上传
+          console.log("切片上传");
+          // 上传的配置
+          options={
+            // 阿里云
+            OSS:{
+              // 设置并发上传的分片数量。
+              parallel: 10,
+              // 设置分片大小。默认值为1 MB,最小值为100 KB。
+              partSize: 1024 * 1024 * 10, // 10MB
+            },
+            /**
+             * minIO的上传方法自动将较大的文件进行分片,不需要特殊配置
+             * 官网文档翻译文:单个对象的最大大小限制为5TB。putObject透明地将大于64MiB的对象分成多个部分上传。使用MD5SUM签名仔细验证上传的数据。
+             */
+            //S3
+            S3:{
+              partSize: 10 * 1024 * 1024, // 设置每个分片大小为10MB,默认为8MB。
+              queueSize: 10, // 并发数,默认为4。
+            }
+          }
+        }
+        // uploadFileDirect(clientType,file.raw,temName,options).then(res=>{
+          setTimeout(()=>{
+            console.log(this.current,this.last,'current','last');
+            if(!this.diaShow || (this.current!=this.last)) return 
+            this.fileList.push({name:fileFront,fileUrl:'res',size:this.sizeFormat(file.size),type:"音频"})
+            this.deleteUploadItem(fileFront)
+          },10000)
+          // }).finally(()=>{
+
+          // })
+      },
+      sizeFormat(s){
+        let size = Number(s)
+        if(size<1024){
+          return size+'B'
+        }else if(size<(1024*1024)){
+          return Math.floor((size/1024)*100)/100 +'KB'
+        }else{
+          return Math.floor((size/1024/1024)*100)/100 +'MB'
+        }
+      },
+      deleteUploadItem(name){
+        let index = this.uploadingFileNames.findIndex(fileName=> fileName==name)
+        if(index!=-1){
+          this.uploadingFileNames.splice(index,1)
+        }
+      },
+      checkDuration(file){
+        return new Promise((resolve,reject)=>{
+          try {
+            let url = URL.createObjectURL(file.raw);
+            
+            let audioElement = new Audio(url);
+            audioElement.addEventListener('loadeddata', () => {
+              if(audioElement.duration>(60*60*5+1)){
+                resolve({flag:false,msg:file.name+'时长已超限'})
+              }else{
+                resolve({flag:true,msg:''})
+              }
+            });
+            setTimeout(()=>{
+              resolve({flag:false,msg:file.name+"获取不到时长,请重试"})
+            },5000)
+          } catch (error) {
+            this.$message.error(error.msg)
+            console.error(error.msg);
+            reject(error)
+          }
+        })
+      },
+      deleteFile(index){
+        this.fileList.splice(index,1)
+      },
+      cancelHandle(){
+        this.$emit("update:diaShow",false)
+      },
+      saveHandle(){
+        if(this.uploadingFileNames && this.uploadingFileNames.length>0){
+          return this.$message.error("还有音/视频未上传完成,请等待上传成功后再转写!") 
+        } 
+        this.$refs.diaForm.validate(valid=>{
+          if(valid){
+            //TODO: 转写接口调用
+            this.$message.success("提交转写成功")
+            this.$emit("uploadSuccess")
+            this.$emit("update:diaShow",false)
+          }
+        })
+      },
+      closeHandle(){
+        this.formData={}
+        this.closeDia=true
+        this.uploadingFileNames=[]
+        this.fileList=[]
+        this.last++
+        this.$emit("update:diaShow",false)
+        this.$nextTick(()=>{
+          this.$refs.diaForm.clearValidate()
+          this.closeDia=false
+        })
+      }
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+  @mixin font-type {
+    font-size: 14px;
+    line-height: 22px;
+    font-weight: 400;
+    color: #333333;
+  }
+.dialog-main{
+  padding: 5px 35px 35px;
+  .file-upload-zone{
+    .file-upload-title{
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      span{
+        @include font-type
+      }
+      .file-readdition{
+        color: #0052D9;
+        cursor: pointer;
+      }
+      .disable-readdition{
+        color: #999999;
+        cursor:not-allowed;
+      }
+    }
+    .file-upload-main{
+      width: 100%;
+      height: 380px;
+      box-sizing: border-box;
+      // border: 1px solid #C8CDD9;
+      background-color: #ECF2FE;
+      border-radius: 4px;
+      margin-top: 10px;
+      .table-span{
+        @include font-type;
+      }
+      .table-button{
+        @include font-type;
+        color: #C54322;
+        cursor: pointer;
+      }
+      .no-file-show{
+        height: 332px;
+        width: 100%;
+        box-sizing: border-box;
+        padding: 130px 0 30px;
+        cursor: pointer;
+        .upload-text{
+          margin-bottom:80px;
+          @include font-type
+        }
+        .upload-message-box{
+          text-align: left;
+          padding-left: 30px;
+          .upload-message-row{
+            @include font-type;
+            color: #666666;
+          }
+        }
+      }
+    }
+  }
+  .dia-bot{
+    text-align: center;
+    margin-top: 60px;
+  }
+}
+</style>
+<style lang="scss">
+  @mixin font-type {
+    font-size: 14px;
+    line-height: 22px;
+    font-weight: 400;
+    color: #333333;
+  }
+.el-cascader-node{
+  max-width: 200px;
+}
+#media-upload-cascader{
+  .el-input{
+    width: 100%;
+  }
+}
+#file-list-table{
+  background-color: #ECF2FE;
+  border: 1px solid #C8CDD9;
+  border-radius: 4px;
+  th{
+    background-color: #ECF2FE!important;
+    border-color: #C8CDD9!important;
+    @include font-type;
+    color: #999999;
+  }
+  td{
+    border: none;
+    background-color: #ECF2FE!important;
+    padding: 10px 0;
+  }
+  .el-table__body-wrapper{
+    height: 332px;
+    overflow-y: auto;
+  }
+  .el-table__empty-block{
+    .el-table__empty-text{
+      width: 100%;
+      color: unset;
+      line-height: unset;
+    }
+  }
+}
+</style>

+ 162 - 0
src/views/semantics_manage/asr/components/transferStatus.vue

@@ -0,0 +1,162 @@
+<template>
+  <div v-if="windowShow" class="transfer-status-box" id="transfer-status-box" draggable @dragstart="dragStart"
+    :style="{'height':isFold?'40px':'unset','width':isFold?'210px':'340px',right:x+'px', bottom:y+'px'}">
+    <div class="transfer-status-header">
+      <div class="status-header-left">
+        <img src="~@/assets/img/smartReport/icon02.png" :draggable="false" />
+        <span>转写中({{ transferStatus.transferingNumber || 0 }})</span>
+      </div>
+      <div class="status-header-right">
+        <img src="~@/assets/img/icons/arrow_black_up.png" style="margin-right: 12px;" @click="isFold=!isFold"
+        :style="{'transform':isFold?'rotate(180deg)':'rotate(0)'}"  :draggable="false"/>
+        <img src="~@/assets/img/icons/close.png" @click="closeWindow"  :draggable="false"/>
+      </div>
+    </div>
+    <div class="transfer-status-body" >
+      <div class="transfer-status-row" v-for="(item,index) in transferStatus.list" :key="item.name">
+        <div class="status-body-name">
+          <span>{{ item.name }}</span>
+          <span v-if="item.status==2" style="color: #AD352F;">({{ item.statusText }}:{{ item.failReason }})</span>
+        </div>
+        <div class="status-body-right">
+          <img v-if="item.status==2" src="~@/assets/img/icons/delete-red.png" style="cursor: pointer;" 
+          @click="deleteRow(item,index)" :draggable="false"/>
+          <span v-else :style="{'color':item.status==0?'#999999':'#333333'}">{{ item.statusText }}</span>
+        </div>
+      </div>
+    </div>
+    <img id="emptyImage" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" style="display: none;">
+  </div>
+</template>
+
+<script>
+  export default {
+    name:"transferStatus",
+    props:{
+      windowShow:{
+        type:Boolean,
+        default:false
+      },
+      transferStatus:{
+        type:Object,
+        required:true
+      },
+    },
+    data() {
+      return {
+        isFold:true,
+        // 拖拽相关
+        x: 20,
+        y: 20,
+        dragOffsetX: null,
+        dragOffsetY: null,
+        dragDocument:null
+      }
+    },
+    mounted(){
+      this.$nextTick(()=>{
+        this.dragDocument = $('#transfer-status-box')[0]
+      })
+    },
+    methods: {
+      deleteRow(item,index){
+        this.$emit("deleteRow",{item,index})
+      },
+      closeWindow(){
+        // localStorage.removeItem("transferStatusShow")
+        this.$emit("update:windowShow",false)
+      },
+      dragStart(event) {
+        // 计算鼠标位置偏移量
+        this.dragOffsetX = event.clientX - event.target.getBoundingClientRect().left;
+        this.dragOffsetY = event.clientY - event.target.getBoundingClientRect().top;
+        
+        event.dataTransfer.effectAllowed='move'
+        // 去掉虚影
+        event.dataTransfer.setDragImage(emptyImage, 0, 0);
+
+        document.addEventListener('dragover',this.dragover)
+        document.addEventListener('dragend',this.dragend)
+      },
+      dragover(event){
+        // 防止默认处理
+        event.preventDefault();
+
+        // 计算新位置,并更新组件的 x 和 y 数据属性
+
+        this.x = window.innerWidth-(event.clientX - this.dragOffsetX) - this.dragDocument.clientWidth
+        this.y = window.innerHeight-(event.clientY - this.dragOffsetY) - this.dragDocument.clientHeight
+
+      },
+      dragend(event) {
+        // 防止默认处理
+        event.preventDefault();
+
+        document.removeEventListener('dragover',this.dragover)
+        document.removeEventListener('dragend',this.dragend)
+      }
+    },
+  }
+</script>
+
+<style lang="scss" scoped>
+
+@mixin font-type{
+  font-size: 14px;
+  font-weight: 400;
+  line-height: 20px;
+  color:#333333;
+}
+
+.transfer-status-box{
+  width: 340px;
+  padding: 10px 20px;
+  box-sizing: border-box;
+  background-color: white;
+  overflow: hidden;
+  border-radius: 4px;
+  border: 1px solid #C8CDD9;
+  z-index: 1000;
+  img{
+    height: 16px;
+    width: 16px;
+  }
+  span{
+    @include font-type;
+  }
+  .transfer-status-header{
+    padding-bottom: 10px;
+    border-bottom: 1px solid #C8CDD9;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    .status-header-left{
+      display: flex;
+      align-items: center;
+      img{
+        margin-right: 4px;
+      }
+    }
+    .status-header-right{
+      img{
+        cursor: pointer;
+      }
+    }
+  }
+  .transfer-status-body{
+    margin-top: 10px;
+    max-height: 90px;
+    overflow-y: auto;
+    box-sizing: border-box;
+    .transfer-status-row{
+      margin-top: 10px;
+      display: flex;
+      align-items: flex-start;
+      justify-content: space-between;
+      // .status-body-name{
+      // }
+    }
+  }
+
+}
+</style>

Some files were not shown because too many files changed in this diff